我刚学会了Haskell中的无点样式,以及它如何帮助整理代码并使其更易于阅读。但有时他们可以使代码有点过于简洁。
所以,当我应该总是使用无点样式时,在什么情况下我应该绝对避免在Haskell中使用无点样式?
答案 0 :(得分:5)
正如已经评论过的,这是一个品味问题,并且总会有两种风格同样适合的边缘情况(或者,实际上,部分指向的版本是最好的)。但是,在某些情况下,它足够清楚:
如果尖头表达式可以像这样减少η,那么这通常是个好主意。
f x = g (h x)
应该写得更好
f = g . h
如果要在接受某些函数参数之前记忆一些计算,则必须将这些参数保留在范围之外。例如,
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps x = a * x + b
where a, b = -- expensive calculation of regression coefficients,
-- depending on the `ps`
在性能方面不是最佳的,因为需要为接收到的每个x
值重新计算系数。如果你点免费:
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps = (+b) . (a*)
where a, b = ...
这个问题不会出现。 (也许GHC在某些情况下会自行解决这个问题,但我不会依赖它。)
通常情况下,最好不要指出它,而不是x
与a
和b
在同一范围内,而是由专用的lambda绑定:
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps = \x -> a * x + b
where a, b = ...
如果无点版本实际上更长而不是指向版本,我就不会使用它。如果你需要引入一些技巧来使它像flip
和Monad (a->)
实例一样无点,这甚至不会缩短它,那么它几乎肯定会比尖头版本更不易读。 / p>
答案 1 :(得分:3)
我最喜欢的答案来自Richard Bird的使用Haskell进行功能性思考:pointfree风格帮助您推理功能组合,而尖锐的风格可以帮助您推理功能应用
如果您发现编写特定函数的无点样式很尴尬,那么通常有两个选项:
在我自己的程序中,我发现(2)经常导致更好的设计,然后可以使用无点样式更清晰地表达这种设计。 Pointfree风格不是最终目标:它是实现更多组合设计的一种手段。