好的Haskell编码标准
有人可以提供一个良好的Haskell编码标准的链接? 我已经find这个和这个 ,但是他们还不够全面。 更不用说HaskellWiki包含了像“谨慎使用类”和“定义符号中缀标识符”这样的“gem”应该只留给图书馆作者。
真的很难的问题。 我希望你的答案有好的一面。 同时,这里是我在初学者的代码中发现的错误或其他恼人的事情的目录。 与Kornel Kisielewicz指出的Cal Tech风格页面有一些重叠。 我的一些build议是像HaskellWiki“gem”一样模糊和无用,但我希望至less这是更好的build议:-)
-
格式化您的代码,使其适合80列。 (高级用户可能更喜欢87或88;除此之外,推动它。)
-
不要忘记,
let
绑定和where
子句创build一个定义的相互recursion嵌套, 而不是 一系列的定义。 -
利用
where
子句,特别是看看已经在范围内的函数参数的能力(很好的模糊build议)。 如果你真的在寻找Haskell,你的代码应该比-bindings更多地使用-bindings。let
-bindings过多是未被重build的ML程序员或Lisp程序员的标志。 -
避免多余的括号。 有些地方冗余的括号是特别冒犯的
-
在
if
expression式的条件下(把你当作一个未被重build的C程序员来标记) -
围绕一个函数应用程序本身就是一个中缀运算符( 函数应用程序比任何中缀运算符都更紧密)的参数,这个事实应该被刻录到每一个Haskeller的大脑中,就像我们恐龙拥有APL的从右到左的扫描规则烧伤)
-
-
在中缀运算符周围放置空格。 在每个逗号之后放置一个空格在一个元组文字中。
-
在函数和它的参数之间加一个空格,即使参数是加了括号的。
-
明智地使用
$
操作符来减less括号。 注意$
和中缀之间的密切关系.
:f $ g $ hx == (f . g . h) x == f . g . h $ x
-
不要忽视内置的
Maybe
和Either
types。 -
if <expression> then True else False
不要写if <expression> then True else False
; 正确的短语就是<expression>
。 -
当你可以使用模式匹配时,不要使用
head
或tail
。 -
不要忽略中缀点运算符的function组合。
-
仔细使用换行符。 换行可以提高可读性,但是有一个折衷:您的编辑器可能一次只显示40-50行。 如果您需要同时阅读和理解大型函数,则不能过分使用换行符。
-
几乎总是比较喜欢那些以
{- ... -}
注释结尾的注释。 支持的评论可能适合大标题 – 就是这样。 -
给每个顶级函数一个明确的types签名。
-
在可能的情况下,alignment
--
行,=
符号,甚至在相邻行中出现的括号和逗号。 -
受GHC中心影响,我有一个非常温和的偏好使用
camelCase
导出的标识符和short_name
与下划线为本地where
或绑定的variables。
一些很好的经验法则:
- 请咨询HLint ,以确保您没有冗余大括号,并且您的代码不是毫无意义的点满。
- 避免重新创build现有的库函数。 Hoogle可以帮助您find它们。
- 很多时候,现有的图书馆function比人们所要做的要普遍。 例如,如果你想要
Maybe (Maybe a) -> Maybe a
,然后join
做其他事情。
- 很多时候,现有的图书馆function比人们所要做的要普遍。 例如,如果你想要
- 有时参数命名和文档很重要。
- 对于像
replicate :: Int -> a -> [a]
这样的函数来说,每个参数的作用都是非常明显的。 - 对于一个接受多个相同types参数的函数,比如
isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
,参数的命名/logging更重要。
- 对于像
- 如果一个函数只是为了另一个函数而存在,并且没有其他用处,并且/或者很难为其命名,那么它可能应该存在于调用者的
where
子句中而不是模块的作用域中。 - 干
- 适当时使用Template-Haskell。
- 捆绑的function,如
zip3
,zipWith3
,zip4
,zipWith4
等是非常meh。 改为使用Applicative
于ZipList
的样式。 你可能从来没有真正需要这样的function。 - 自动派生实例。 派生包可以帮助你派生types的实例,例如
Functor
(只有一个正确的方法可以使types成为Functor
一个实例)。
- 更一般的代码有几个好处:
- 这更有用,可重用。
- 因为有更多的限制,所以不太容易出错。
- 例如,如果你想编程
concat :: [[a]] -> [a]
,并注意到它可以更加通用,如join :: Monad m => m (ma) -> ma
。 编程join
时出现错误的空间较小,因为编程concat
时可以错误地反转列表,并且在join
中可以做的事情很less。
- 例如,如果你想编程
- 在代码中的许多地方使用相同的monad变换器堆栈时,为其创build一个types同义词。 这将使得types更短,更简洁,并且更容易批量修改。
- 当心“懒惰IO”。 例如,
readFile
在读取文件的时候并不真正读取文件的内容。 - 避免缩进,以至于找不到代码。
- 如果你的types在逻辑上是一个types的实例,把它作为一个实例。
- 这个实例可以replace您熟悉的其他接口函数。
- 注意:如果有多个逻辑实例,则为实例创buildnewtype-wrappers。
- 使不同的实例保持一致。 如果列表
Applicative
行为像ZipList
一样,那将会非常令人困惑/不好。
我build议看看这个风格检查 。
-
我喜欢尽可能地通过做一些事情来尽可能地将function组织为无点式的组合,例如:
func = boo . boppity . bippity . snd where boo = ... boppity = ... bippity = ...
-
我喜欢只使用($)来避免嵌套parens或长括号expression式
-
…我想我还有更多的在我身上,哦,好吧
我发现很好的降价文件,涵盖了haskell代码风格的几乎每一个方面。 它可以用作备忘单。 你可以在这里find它: 链接