为什么 Haskell 中的函数组合是右结合的?

2024-01-19

从数学上讲,函数复合运算是结合的。因此:

f . (g . h) = (f . g) . h

因此,函数复合运算可以被定义为左关联或右关联。

由于 Haskell 中的正常函数应用(即术语的并置,而不是$我认为函数组合也应该是左关联的。毕竟世界上大多数人(包括我自己)都习惯从左到右阅读。

然而 Haskell 中的函数组合是右结合的:

infixr 9 .

我知道函数组合操作是左关联还是右关联并没有真正的区别。不过我很好奇为什么它不保留关联性。我做出这个设计决定有两个原因:

  1. Haskell 的创建者希望函数组合在逻辑上与$手术。
  2. Haskell 的创建者之一是一位日本人,他发现将函数组合设为右关联而不是左关联更直观。

抛开笑话不谈,函数组合在 Haskell 中具有右关联性有什么有益的理由吗?如果 Haskell 中的函数组合保持关联,会有什么不同吗?


在存在非严格求值的情况下,右结合性是有用的。让我们看一个非常愚蠢的例子:

foo :: Int -> Int
foo = const 5 . (+3) . (`div` 10)

好吧,当这个函数的计算结果为 0 时会发生什么. is infixr?

foo 0
=> (const 5 . ((+3) . (`div` 10))) 0
=> (\x -> const 5 (((+3) . (`div` 10)) x)) 0
=> const 5 (((+3) . (`div` 10)) 0)
=> 5

现在,如果. was infixl?

foo 0
=> ((const 5 . (+3)) . (`div` 10)) 0
=> (\x -> (const 5 . (+3)) (x `div` 10)) 0
=> (const 5 . (+3)) (0 `div` 10)
=> (\x -> const 5 (x + 3)) (0 `div` 10)
=> const 5 ((0 `div` 10) + 3)
=> 5

(我有点累了。如果我在这些减少步骤中犯了任何错误,please让我知道,或者只是修复它们..)

他们有相同的结果,是的。但减少的步数并不相同。什么时候.是左关联的,组合操作可能需要减少更多次 - 特别是,如果链中较早的函数决定快捷方式,以便不需要嵌套计算的结果。最坏的情况是相同的,但在最好的情况下,右关联性可能会获胜。因此,选择有时更好的选择,而不是有时更差的选择。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Haskell 中的函数组合是右结合的? 的相关文章

随机推荐