为什么这个Haskell代码不会终止?

Ste*_*haw 13 haskell

为什么以下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是一个红色鲱鱼 - 它出现在最里面的应用中||,而不是最外层,所以它永远无法实现.


fuz*_*fuz 9

问题很明显,如果您foldr手动展开:

foldr (||) True $ repeat False == False || (False || (False (False || ... True)))
Run Code Online (Sandbox Code Playgroud)

因此,为了获得最终结果False,代码必须评估列表直到其(不存在)结束.在您的第二个示例中,您重复True,因此可以进行短路评估.不要期待魔法从懒惰的评价!

  • 你在展开时交换了True和False. (2认同)