简体   繁体   English

为什么此Haskell代码不终止?

[英]Why does this Haskell code not terminate?

Why does the following Haskell code not terminate: 为什么以下Haskell代码不会终止:

foldr (||) True $ repeat False -- never terminates

when something like this does: 当这样的事情发生时:

foldr (||) False $ repeat True -- => True

To me, it's the second expression that looks to be in more trouble of not terminating. 对我来说,这是第二种表达方式,似乎很难终止。 What's wrong with my view of Haskell's lazy evaluation? 我对Haskell的惰性评估有何看法?

I think your understanding of lazy is correct, but not for foldr . 我认为您对懒惰的理解是正确的,但对于文件foldr却不是。 Let's look at its " specification " 让我们看一下它的“ 规范

foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)

Then look at your expression 然后看看你的表情

foldr (||) True $ repeat False -- never terminates

As you see the True ( z ) which we are "looking for" to get || 如您所见,我们正在“寻找”得到||Truez to terminate won't be reached until the whole list is consumed. 在整个列表消耗完之前,无法终止。 And that won't happen as the list is infinite. 由于列表是无限的,因此不会发生这种情况。

This should also explain for the actually terminating example. 这也应为实际终止的示例进行解释。

The first expands to False || (False || (False || ...)) 第一个扩展为False || (False || (False || ...)) False || (False || (False || ...)) , while the second expands to True || (True || (True || ...)) False || (False || (False || ...)) ,而第二个扩展为True || (True || (True || ...)) True || (True || (True || ...)) . True || (True || (True || ...)) The second argument to foldr is a red herring - it appears in the innermost application of || foldr的第二个参数是红色鲱鱼-它出现在||的最内部应用程序中 , not the outermost, so it can never actually be reached. ,而不是最外层,因此永远无法实现。

The problem is quite obvious, if you unfold the foldr manually: 如果您手动展开文件foldr ,则问题很明显:

foldr (||) True $ repeat False == False || (False || (False (False || ... True)))

So in order to get the final False , the code had to evaluate the list till its (nonexistant) end. 因此,为了获得最终的False ,代码必须对列表进行评估,直到列表结束(不存在)为止。 In your second example, you repeat True , thus short-circuit evaluation is possible. 在第二个示例中,重复True ,因此可以进行短路评估。 Don't expect magic from lazy evaluation! 不要期望懒惰的评估会带来魔力!

A yet another insight for you is that || 对您来说,另一种见解是|| is not commutative in Haskell, it's biased : 在Haskell中不是可交换的,它是有偏见的

Prelude> undefined || True
*** Exception: Prelude.undefined
Prelude> True || undefined
True

So unlike in math, || 因此,与数学不同, || and flip (||) are different functions. flip (||)是不同的功能。 Eg compare 例如比较

foldr (||) False $ repeat True and foldr (flip (||)) False $ repeat True foldr (||) False $ repeat True和文件foldr (flip (||)) False $ repeat True

The former terminates, but the latter don't. 前者终止,但后者不终止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM