【发布时间】:2012-06-13 21:43:16
【问题描述】:
我很好奇无限列表的运行时性能,例如 下一个:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
这将创建一个无限的斐波那契数列列表。
我的问题是,如果我执行以下操作:
takeWhile (<5) fibs
fibs 评估列表中的每个术语多少次?它似乎
因为takeWhile 检查每个项目的谓词函数
列表中,fibs 列表将多次评估每个术语。这
前 2 个学期免费提供。当takeWhile 想要评估时
(<5) 在第三个元素上,我们会得到:
1 : 1 : zipWith (+) [(1, 1), (1)] => 1 : 1 : 3
现在,一旦 takeWhile 想要在第 4 个元素上评估 (<5):
fibs 的递归性质将再次构造列表,如
以下:
1 : 1 : zipWith (+) [(1, 2), (2, 3)] => 1 : 1 : 3 : 5
似乎我们需要再次计算第三个元素
想要评估第 4 个元素的值。此外,如果
takeWhile 中的谓词很大,表示函数是
做更多需要做的工作,因为它正在评估前面的每一个
列表中的元素多次。我的分析是正确的还是
Haskell 做一些缓存来防止这里的多次评估?
【问题讨论】:
-
2(通常出现在标准斐波那契数列中的1和3之间)发生了什么? -
当然取决于实现,但一个体面的人只会评估列表中的每个元素一次。