为什么以下Haskell代码不会终止:
foldr (||) True $ repeat False -- never terminates
Run Code Online (Sandbox Code Playgroud)
当这样的事情:
foldr (||) False $ repeat True -- => True
Run Code Online (Sandbox Code Playgroud)
对我来说,这是第二个看起来更难以终止的表达.我对Haskell懒惰评估的看法有什么问题?
Tar*_*sch 18
我认为你对懒惰的理解是正确的,但不是foldr.让我们来看看它的" 规格 "
foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)
Run Code Online (Sandbox Code Playgroud)
然后看看你的表情
foldr (||) True $ repeat False -- never terminates
Run Code Online (Sandbox Code Playgroud)
正如你所看到的True(z),我们正在"寻找"来获得||终止不会达到直到整个列表被消耗.这不会发生,因为列表是无限的.
这也应该解释实际终止的例子.
mok*_*kus 13
第一个扩展到False || (False || (False || ...)),而第二个扩展到True || (True || (True || ...)).第二个参数foldr是一个红色鲱鱼 - 它出现在最里面的应用中||,而不是最外层,所以它永远无法实现.
问题很明显,如果您foldr手动展开:
foldr (||) True $ repeat False == False || (False || (False (False || ... True)))
Run Code Online (Sandbox Code Playgroud)
因此,为了获得最终结果False,代码必须评估列表直到其(不存在)结束.在您的第二个示例中,您重复True,因此可以进行短路评估.不要期待魔法从懒惰的评价!