良好的 Haskell 编码标准
有人可以提供一个良好的 Haskell 编码标准的链接吗?我找到了这个和这个,但它们远非全面。更不用说 HaskellWiki 中包含了诸如“小心使用类”和“定义符号中缀标识符应该只留给库编写者”这样的“宝石”。
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."
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
真的很难回答。我希望你的回答能带来好的结果。同时,这里是我在初学者代码中发现的错误或其他烦人的事情的目录。与 Kornel Kisielewicz 指出的加州理工学院风格页面有一些重叠。我的一些建议与 HaskellWiki“宝石”一样模糊且无用,但我希望至少这是更好的建议:-)
格式化你的代码,使其适合 80 列。 (高级用户可能更喜欢 87 或 88;除此之外,它正在推动它。)
不要忘记
let
绑定和where
子句创建相互递归的定义嵌套,不是定义的序列。利用
where
子句,尤其是它们查看已在范围内的函数参数的能力(很好的模糊建议)。如果您真正熟悉 Haskell,那么您的代码中的where
绑定应该比let
绑定多得多。太多let
绑定是未重构的 ML 程序员或 Lisp 程序员的标志。避免多余的括号。一些多余括号特别令人反感的地方是
围绕
if
表达式中的条件(将您标记为未重构的 C 程序员)围绕一个函数应用程序,它本身就是中缀运算符的参数(函数应用程序比任何中缀运算符绑定得更紧密。这个事实应该铭刻在每个 Haskeller 的大脑中,同样的道理我们恐龙就这样铭记了 APL 从右到左的扫描规则。)
在中缀运算符周围放置空格。在元组文字中的每个逗号后面放置一个空格。
首选函数及其参数之间有空格,即使参数带括号。
明智地使用
$
运算符来减少括号的数量。请注意$
和中缀.
之间的密切关系:不要忽视内置的
Maybe
和Either
类型。永远不要写
if <表达式>;然后为 True,否则为 False
;正确的短语是<表达式>
。当可以使用模式匹配时,不要使用
head
或tail
。不要忽视使用中缀点运算符的函数组合。
小心使用换行符。换行符可以提高可读性,但需要权衡:您的编辑器一次可能只显示 40-50 行。如果您需要一次阅读并理解一个大函数,则一定不要过度使用换行符。
几乎总是更喜欢运行到行尾的
--
注释,而不是{- ... -}
注释。大括号注释可能适合大标题 - 就是这样。为每个顶级函数提供显式类型签名。
如果可能,请对齐
--
行、=
符号,甚至相邻行中出现的括号和逗号。受 GHC 中心的影响,我非常倾向于使用
camelCase
来表示导出的标识符,使用short_name
来表示本地where
并使用下划线>-bound 或let
-bound 变量。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.一些好的经验法则恕我直言:
Maybe (Maybe a) ->也许是一个
,然后join
就可以做到这一点。replicate :: Int -> 这样的函数一个-> [a]
,每个参数的作用非常明显,仅从它们的类型来看。where
子句中,而不是在模块的范围内。zip3
、zipWith3
、zip4
、zipWith4
等函数包非常无聊。请使用带有ZipList
的Applicative
样式。您可能永远不会真正需要这样的功能。Functor
(只有一种正确的方法可以使类型成为Functor
的实例)。concat :: [[a]] -> [a]
,并注意它如何变得更通用,如join :: Monad m =>; m(ma)-> m a.
.在编写join
时出错的空间较小,因为在编写concat
时,您可能会错误地反转列表,而在join
中,您几乎不需要做任何事情。可以做。Applicative
的行为类似于ZipList
,那将会非常混乱/糟糕。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
.我喜欢尝试组织功能
作为无点风格的作品
尽可能地做事
像:
我喜欢使用 ($) 只是为了避免嵌套括号或长括号表达式
...我以为我有一个我身上还有更多,哦,好吧
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'd suggest taking a look at this style checker.
我发现很好的 Markdown 文件几乎涵盖了 Haskell 代码风格的各个方面。它可以用作备忘单。您可以在这里找到它:链接
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