Could someone provide a link to a good coding standard for Haskell? I've found this and this, but they are far from comprehensive. Not to mention that the HaskellWiki one includes such "gems" as "use classes with care" and "defining symbolic infix identifiers should be left to library writers only."
相关问题
- Understanding do notation for simple Reader monad:
- Making Custom Instances of PersistBackend
- Haskell: What is the differrence between `Num [a]
- applying a list to an entered function to check fo
- Haskell split a list into two by a pivot value
相关文章
- Is it possible to write pattern-matched functions
- Haskell underscore vs. explicit variable
- Top-level expression evaluation at compile time
- Stuck in the State Monad
- foldr vs foldr1 usage in Haskell
- List of checkboxes with digestive-functors
- How does this list comprehension over the inits of
- Python relative import with more than two dots
Some good rules of thumbs imho:
Maybe (Maybe a) -> Maybe a
, thenjoin
does that among other things.replicate :: Int -> a -> [a]
, it's pretty obvious what each of the arguments does, from their types alone.isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
, naming/documentation of arguments is more important.where
clause instead of in the module's scope.zip3
,zipWith3
,zip4
,zipWith4
, etc are very meh. UseApplicative
style withZipList
s instead. You probably never really need functions like those.Functor
(there is only one correct way to make a type an instance ofFunctor
).concat :: [[a]] -> [a]
, and notice how it can be more general asjoin :: Monad m => m (m a) -> m a
. There is less room for error when programmingjoin
because when programmingconcat
you can reverse the lists by mistake and injoin
there are very few things you can do.readFile
doesn't really read the file's contents at the moment the file is read.Applicative
behaved likeZipList
.Really hard question. I hope your answers turn up something good. Meanwhile, here is a catalog of mistakes or other annoying things that I have found in beginners' code. There is some overlap with the Cal Tech style page that Kornel Kisielewicz points to. Some of my advice is every bit as vague and useless as the HaskellWiki "gems", but I hope at least it is better advice :-)
Format your code so it fits in 80 columns. (Advanced users may prefer 87 or 88; beyond that is pushing it.)
Don't forget that
let
bindings andwhere
clauses create a mutually recursive nest of definitions, not a sequence of definitions.Take advantage of
where
clauses, especially their ability to see function parameters that are already in scope (nice vague advice). If you are really grokking Haskell, your code should have a lot morewhere
-bindings thanlet
-bindings. Too manylet
-bindings is a sign of an unreconstructed ML programmer or Lisp programmer.Avoid redundant parentheses. Some places where redundant parentheses are particularly offensive are
Around the condition in an
if
expression (brands you as an unreconstructed C programmer)Around a function application which is itself the argument of an infix operator (Function application binds tighter than any infix operator. This fact should be burned into every Haskeller's brain, in much the same way that us dinosaurs had APL's right-to-left scan rule burned in.)
Put spaces around infix operators. Put a space following each comma in a tuple literal.
Prefer a space between a function and its argument, even if the argument is parenthesized.
Use the
$
operator judiciously to cut down on parentheses. Be aware of the close relationship between$
and infix.
:Don't overlook the built-in
Maybe
andEither
types.Never write
if <expression> then True else False
; the correct phrase is simply<expression>
.Don't use
head
ortail
when you could use pattern matching.Don't overlook function composition with the infix dot operator.
Use line breaks carefully. Line breaks can increase readability, but there is a tradeoff: Your editor may display only 40–50 lines at once. If you need to read and understand a large function all at once, you mustn't overuse line breaks.
Almost always prefer the
--
comments which run to end of line over the{- ... -}
comments. The braced comments may be appropriate for large headers—that's it.Give each top-level function an explicit type signature.
When possible, align
--
lines,=
signs, and even parentheses and commas that occur in adjacent lines.Influenced as I am by GHC central, I have a very mild preference to use
camelCase
for exported identifiers andshort_name
with underscores for localwhere
-bound orlet
-bound variables.I like to try to organize functions as point-free style compositions as much as possible by doing things like:
I like using ($) only to avoid nested parens or long parenthesized expressions
... I thought I had a few more in me, oh well
I found good markdown file covering almost every aspect of haskell code style. It can be used as cheat sheet. You can find it here: link
I'd suggest taking a look at this style checker.