【发布时间】:2011-04-22 16:18:53
【问题描述】:
在 Haskell 中,由于懒惰,您可以构建无限列表:
Prelude> let g = 4 : g
Prelude> g !! 0
4
Prelude> take 10 g
[4,4,4,4,4,4,4,4,4,4]
现在,当我尝试构建这样的列表时究竟发生了什么?
Prelude> let f = f !! 10 : f
Prelude> f !! 0
Interrupted.
Prelude> take 10 f
[Interrupted.
Prelude>
Interrupted.s 是我在等待几秒钟后按下 CTRL+C。它似乎进入了一个无限循环,但为什么会这样呢?
非Haskellers的解释:
: 运算符是prepend:
Prelude> 4 : [1, 2, 3]
[4,1,2,3]
这一行:
Prelude> let g = 4 : g
说“让g 成为通过将4 前置到列表g 中构造的列表”。当您请求第一个元素时,将返回 4,因为它已经存在。当您请求第二个元素时,它会查找 4 之后的元素。该元素将是列表 g 的第一个元素,我们刚刚计算了 (4),因此返回了 4。下一个元素是g 的第二个元素,我们再次计算,等等...
!! 只是索引到一个列表中,所以这意味着从g 获取索引0 处的元素:
Prelude> g !! 0
4
但是当我这样做时:
Prelude> let f = f !! 10 : f
有些东西坏了,因为要计算f 的第一个元素,您需要第 11 个元素,它还不存在?不过,我希望出现异常,而不是无限循环...
【问题讨论】:
-
对于踢球,请尝试以下方法:
length $ take 10 f。一个字:Thunks。也可以试试:length [error "raises an error"]. -
我建议您删除非Haskellers部分的说明。
-
@Wei Hu:如果有很多人点赞你的评论,我会这样做