34

在数学上,函数组合操作是关联的。因此:

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

因此,函数组合操作可以定义为左结合或右结合。

由于 Haskell 中的普通函数应用程序(即术语的并置,而不是$操作)在我看来是左关联的,因此函数组合也应该是关联的。毕竟世界上大多数人(包括我自己)都习惯从左到右阅读。

不过 Haskell 中的函数组合是右结合的:

infixr 9 .

我知道函数组合操作是左关联还是右关联并没有真正的区别。不过,我很想知道为什么它没有留下联想。对于这个设计决策,我想到了两个原因:

  1. Haskell 的制造者希望函数组合在逻辑上与$操作相似。
  2. Haskell 的制造者之一是日本人,他发现将函数组合设为右关联而不是左关联更直观。

撇开玩笑不谈,函数组合在 Haskell 中正确关联是否有任何有益的理由?如果 Haskell 中的函数组合是关联的,会有什么不同吗?

4

1 回答 1

41

在存在非严格评估的情况下,右关联性很有用。让我们看一个非常愚蠢的例子:

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

好的,当这个函数在 is 时被评估为 0 时会发生.什么infixr

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

现在,如果.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

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

他们有相同的结果,是的。但是减少步骤的数量是不一样的。当.是左关联时,组合操作可能需要减少更多次 - 特别是,如果链中较早的函数决定使用快捷方式以使其不需要嵌套计算的结果。最坏的情况是一样的,但在最好的情况下,右关联可能是一个胜利。所以选择有时更好的选择,而不是有时更糟的选择。

于 2013-12-03T06:22:26.253 回答