Haskell 复合函数(.)和函数应用程序($)习惯用法: 正确使用

我一直在阅读 真实世界 Haskell,我已经接近尾声,但一个风格的问题一直在我与 (.)($)操作员做琐碎。

当你写一个由其他函数组成的函数时,你可以这样写:

f = g . h

但是当你把一些东西应用到这些函数的末尾时,我把它写成这样:

k = a $ b $ c $ value

但这本书是这样写的:

k = a . b . c $ value

现在,对我来说,它们看起来功能相当,它们在我眼中做着完全相同的事情。然而,我看得越多,就越能看到人们按照书中的方式编写函数: 首先使用 (.)编写,然后只在最后使用 ($)附加一个值来评估批次(没有人使用很多美元编写)。

是否有一个原因使用书籍的方式比使用所有 ($)符号好得多?还是有什么我没有得到的最佳实践?或者这是多余的,我根本不用担心?

23834 次浏览

只是风格问题。然而,这本书的写作方式对我来说更有意义。它组合所有函数,然后将其应用于值。

您的方法看起来很奇怪,最后一个 $是不必要的。

然而,这并不重要,在哈斯克尔,做同样的事情通常有很多很多正确的方法。

我想我可以从权威部门回答这个问题。

是否有一个使用书籍的方式比使用所有($)符号好得多的原因?

没什么特别的原因。布莱恩和我都喜欢降低线路噪音。.$安静。因此,本书使用了 f . g . h $ x语法。

它们实际上是等价的: 请记住,$操作符基本上什么也不做。f $ x评估为 f x$的目标是它的固定行为: 右结合和最小优先级。删除 $并使用圆括号代替中缀优先级进行分组,代码片段如下所示:

k = a (b (c (value)))

还有

k = (a . b . c) value

选择 .版本而不是 $版本的原因与选择两者而不是上面插入的非常漂亮的版本的原因是一样的: 美观。

不过,有些人可能会怀疑,使用中缀运算符而不使用括号,是否是出于某种潜意识的驱使,希望避免与 Lisp 有任何可能的相似之处(开玩笑的... ... 我想?).

对我来说,我认为答案是(a)整洁,如 唐说; 和(b)我发现,当我编辑代码时,我的函数可能会以无点风格结束,然后我所要做的就是删除最后一个 $,而不是返回并改变一切。一个小问题,当然,但是一个细节。

Haskell 咖啡店的线上有一个关于这个问题的有趣讨论。显然有少数观点认为 $的正确结合性是 “大错特错”,选择 f . g . h $ x而不是 f $ g $ h $ x是回避这个问题的一种方法。

我要补充的是,在 f . g $ x中,f . g是一个有意义的句法单位。

同时,在 f $ g $ x中,f $ g不是一个有意义的单位。$链可以说是更加必要的—— 第一获得 xg的结果,那么对它做 f那么对它做 foo那么等等。

与此同时,.链可以说更具有声明性,在某种意义上更接近于以数据流为中心的视图——组成一系列函数,并最终将它们应用于某些东西。

我知道这是一个非常古老的问题,但我认为还有一个没有被提及的原因。

如果声明一个新的无点函数 f . g . h,则将自动应用您传入的值。但是,如果编写 f $ g $ h,它将无法工作。

笔者认为,作者之所以倾向于采用组合法,是因为这种方法有助于建立函数的良好实践。