我意识到这可能被认为是一个主观的或离题的问题,所以我希望与其关闭它,不如将它迁移到程序员身上。
我开始学习 Haskell,主要是为了我自己的启迪,我喜欢很多支持该语言的想法和原则。在参加了一个语言理论课后,我开始对函数式语言着迷,我们在那里玩了 Lisp,而且我听到了很多关于 Haskell 高效的好消息,所以我想我自己去研究一下。到目前为止,我喜欢这门语言,除了一件事我无法摆脱:那些母亲 effing 函数签名。
我的专业背景主要是做OO,尤其是Java。我工作过的大多数地方都遵循了许多标准的现代教条。Agile、Clean Code、TDD 等。经过几年的工作,它绝对成为了我的舒适区;特别是“好”代码应该是自我记录的想法。我已经习惯了在 IDE 中工作,其中带有非常描述性签名的冗长冗长的方法名称对于智能自动完成和用于导航包和符号的大量分析工具来说不是问题;如果我可以在 Eclipse 中按 Ctrl+Space,然后通过查看方法的名称和与其参数关联的本地范围变量来推断方法正在做什么,而不是拉起 JavaDocs,我就像一头猪一样高兴。
这显然不是 Haskell 社区最佳实践的一部分。我已经阅读了很多关于这个问题的不同意见,我知道 Haskell 社区认为它的简洁性是一个“专业人士”。我已经阅读了如何阅读 Haskell,并且我理解许多决定背后的基本原理,但这并不意味着我喜欢它们;一个字母的变量名等对我来说并不有趣。我承认,如果我想继续使用该语言进行黑客攻击,我将不得不习惯这一点。
但我无法克服函数签名。举个例子,从Learn you a Haskell[...] 's section on function syntax:
bmiTell :: (RealFloat a) => a -> a -> String
bmiTell weight height
| weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!"
| weight / height ^ 2 <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| weight / height ^ 2 <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
我意识到这是一个愚蠢的例子,它只是为了解释守卫和类约束而创建的,但是如果你只检查那个函数的签名,你将不知道它的哪个参数是用来作为权重的或高度。即使您使用Float
orDouble
代替任何类型,它仍然无法立即辨别。
起初,我认为我会很可爱、聪明、聪明,并尝试使用具有多个类约束的更长类型变量名来欺骗它:
bmiTell :: (RealFloat weight, RealFloat height) => weight -> height -> String
这吐出了一个错误(顺便说一句,如果有人可以向我解释该错误,我将不胜感激):
Could not deduce (height ~ weight)
from the context (RealFloat weight, RealFloat height)
bound by the type signature for
bmiTell :: (RealFloat weight, RealFloat height) =>
weight -> height -> String
at example.hs:(25,1)-(27,27)
`height' is a rigid type variable bound by
the type signature for
bmiTell :: (RealFloat weight, RealFloat height) =>
weight -> height -> String
at example.hs:25:1
`weight' is a rigid type variable bound by
the type signature for
bmiTell :: (RealFloat weight, RealFloat height) =>
weight -> height -> String
at example.hs:25:1
In the first argument of `(^)', namely `height'
In the second argument of `(/)', namely `height ^ 2'
In the first argument of `(<=)', namely `weight / height ^ 2'
不完全理解为什么这不起作用,我开始用谷歌搜索,我什至发现了这篇小帖子,它建议命名参数,特别是通过 欺骗命名参数newtype
,但这似乎有点多。
是否没有可接受的方法来制作信息丰富的函数签名?“Haskell 方式”只是为了把所有事情都搞砸吗?