何时使用以及何时不在haskell中使用无点样式?

时间:2016-07-21 12:54:21

标签: function haskell pointfree

我刚学会了Haskell中的无点样式,以及它如何帮助整理代码并使其更易于阅读。但有时他们可以使代码有点过于简洁。

所以,当我应该总是使用无点样式时,在什么情况下我应该绝对避免在Haskell中使用无点样式?

2 个答案:

答案 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在某些情况下会自行解决这个问题,但我不会依赖它。)

    通常情况下,最好不要指出它,而不是xab在同一范围内,而是由专用的lambda绑定:

    linRegression :: [(Double, Double)] -> Double -> Double
    linRegression ps = \x -> a * x + b
     where a, b = ...
    
  • 如果无点版本实际上更长而不是指向版本,我就不会使用它。如果你需要引入一些技巧来使它像flipMonad (a->)实例一样无点,这甚至不会缩短它,那么它几乎肯定会比尖头版本更不易读。 / p>

答案 1 :(得分:3)

我最喜欢的答案来自Richard Bird的使用Haskell进行功能性思考:pointfree风格帮助您推理功能组合,而尖锐的风格可以帮助您推理功能应用

如果您发现编写特定函数的无点样式很尴尬,那么通常有两个选项:

  1. 请改用尖头风格。有时你想要推理申请。
  2. 将您的功能重新设计为具有成分性。
  3. 在我自己的程序中,我发现(2)经常导致更好的设计,然后可以使用无点样式更清晰地表达这种设计。 Pointfree风格不是最终目标:它是实现更多组合设计的一种手段。