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

Cha*_*dan 0 haskell function pointfree

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

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

lef*_*out 5

正如已经评论过的那样,这是一个品味问题,并且总是存在两种风格同样适合的边缘情况(或者,实际上,部分指向的版本是最好的).但是,在某些情况下,它足够清楚:

  • 如果尖锐的表达式可以像这样减少η,那么通常这样做是个好主意.

    f x = g (h x)
    
    Run Code Online (Sandbox Code Playgroud)

    应该写得更好

    f = g . h
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果要在接受某些函数参数之前记忆一些计算,则必须将这些参数保留在范围之外.例如,

    linRegression :: [(Double, Double)] -> Double -> Double
    linRegression ps x = a * x + b
     where a, b = -- expensive calculation of regression coefficients,
                  -- depending on the `ps`
    
    Run Code Online (Sandbox Code Playgroud)

    在性能方面不是最佳的,因为需要针对x接收到的每个值重新计算系数.如果你点免费:

    linRegression :: [(Double, Double)] -> Double -> Double
    linRegression ps = (+b) . (a*)
     where a, b = ...
    
    Run Code Online (Sandbox Code Playgroud)

    这个问题不会出现.(也许GHC在某些情况下会自行解决这个问题,但我不会依赖它.)

    尽管如此,最好还是指出它,但不是与x同一范围相同a,b而是由专用的lambda绑定:

    linRegression :: [(Double, Double)] -> Double -> Double
    linRegression ps = \x -> a * x + b
     where a, b = ...
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果自由点版本实际上是比点的版本,我不会用它.如果你需要引入一些技巧来使它像点flipMonad (a->)实例一样,这甚至不会使它更短,那么它几乎肯定会比尖头版本更不易读.