想逐步了解Haskell中的以下功能

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

我了解到,“小故障”通常是“懒惰的”,因此下一项将“按需”计算,但是我不确定“尾部”函数如何在无限列表上工作。

因此,说明它如何与一些中间数据一起使用将很有帮助。

最佳答案

一开始,评估是这样的:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

如果我们用评估替换fibs,它看起来像这样:
fibs = 0 : 1 : zipWith (+) (0 : 1 : ?) (1 : ?)

其中?表示未评估的thunk。让我们评估fibs的下一个元素:
fibs = 0 : 1 : zipWith (+) (0 : 1 : ?) (1 : ?) ==>
fibs = 0 : 1 : 1 : zipWith (+) (1 : ?) (?)

使用了zipWith的每个参数列表的第一个元素。现在,当我们评估它时,我们也知道下一个thunk的值是什么,我们可以填充它。这使我们可以评估下一个单元格,依此类推:
fibs = 0 : 1 : 1 : zipWith (+) (1 : ?) (?) ==>
fibs = 0 : 1 : 1 : zipWith (+) (1 : 1 : ?) (1 : ?) ==>
fibs = 0 : 1 : 1 : 2 : zipWith (+) (1 : ?) (?) ==>
fibs = 0 : 1 : 1 : 2 : zipWith (+) (1 : 2 : ?) (2 : ?) ==>
fibs = 0 : 1 : 1 : 2 : 3 : zipWith (+) (2 : ?) (?) ==>
...

09-16 05:01