在学习函数式编程的过程中,我看到了Church Rosser theorem的多个引用,特别是钻石属性图,但我没有遇到过很好的代码示例。
如果像Haskell这样的语言可以被视为一种lambda演算,那么必须能够使用语言本身来鼓励一些例子。
如果示例轻松显示步骤或缩减如何导致易于并行执行,我会给予奖励积分。
答案 0 :(得分:17)
所有这些定理都表明,可以通过多条路径减少的表达式必然会进一步简化为一个共同的产品。
例如,拿这段Haskell代码:
vecLenSq :: Float -> Float -> Float
vecLenSq x y =
xsq + ysq
where
xsq = x * x
ysq = y * y
在Lambda微积分中,此函数大致相当于(为了清晰起见而添加了parens,运算符假定为原始):
λ x . (λ y . (λ xsq . (λ ysq . (xsq + ysq)) (y * y)) (x * x))
可以通过首先将β减少应用于xsq
或者通过将β减少应用于ysq
来减少表达式,即“评估顺序”是任意的。可以按以下顺序减少表达式:
λ x . (λ y . (λ xsq . (xsq + (y * y))) (x * x))
λ x . (λ y . ((x * x) + (y * y)))
...或按以下顺序:
λ x . (λ y . (λ ysq . ((x * x) + ysq)) (y * y))
λ x . (λ y . ((x * x) + (y * y)))
结果显然是一样的。
这意味着术语xsq
和ysq
可以独立复制,并且可以并行化它们的缩减。事实上,人们可以将Haskell中的减少并行化:
vecLenSq :: Float -> Float -> Float
vecLenSq x y =
(xsq `par` ysq) `pseq` xsq + ysq
where
xsq = x * x
ysq = y * y
这种并行化实际上在这种特定情况下不会提供优势,因为由于调度开销,顺序执行的两个简单浮点乘法比两个并行乘法更有效,但对于更复杂的操作可能是值得的。