列表理解中的后卫不会终止无限列表吗?

时间:2018-06-27 16:05:03

标签: haskell

我是这样想的:

[i | i <- [1..], i < 5]

会产生

[1, 2, 3, 4]

就像

take 4 [i | i <- [1..]]

一个有限长度的列表。

但不是,这似乎是无限的,因为任何将其视为有限列表的尝试都只会导致挂起(ghci)。

我不确定如何确切地理解这一点。是某种无限生成器,仅在第四项之后什么也不产生,却永不停止吗?

基本上,代码会不断生成新项目,因为它不知道它们永远无法满足条件?

1 个答案:

答案 0 :(得分:5)

您从字面上告诉程序检查无限列表的每个元素,并且仅包括小于5的元素。正如您所说,编译器没有意识到列表的其余元素永远都不会满足条件。如果传递任意列表,即使在理论上也无法在运行时创建这样的证明。它只是按照您说的做,并且会不断检查每个元素。

如果程序由于懒惰求值而没有尝试对结果xs中的1:2:3:4:xs求值,则不一定是bug。服用head应该很好。但是,如果您告诉它找到列表的长度或类似的内容,那将是一个无限循环。

一种(可能是?)想要做的事情的方法是takeWhile,当条件不再成立时,它就会停止。