Haskell 使用scanl和自参考列表的Fibonacci级数

Haskell 使用scanl和自参考列表的Fibonacci级数,haskell,Haskell,我通过ChrisAllen Haskell编程书学习Haskell。我被困在使用scanl和自引用列表定义斐波那契数列的部分。 我理解对以下代码的评估: scanl (+) 1 [1..3] 1 : (scanl (+) ((+) 1 1) [2,3]) 我读到(+)在两个参数中都是严格的,所以我在下一步中用2代替(+)1 1 : (2 : (scanl (+) ((+) 2 2) [3])) 1 : (2 : (4 : (scanl (+) ((+) 4 3) []))) 1 : (2 :

我通过ChrisAllen Haskell编程书学习Haskell。我被困在使用scanl和自引用列表定义斐波那契数列的部分。 我理解对以下代码的评估:

scanl (+) 1 [1..3]
1 : (scanl (+) ((+) 1 1) [2,3])
我读到(+)在两个参数中都是严格的,所以我在下一步中用2代替(+)1

1 : (2 : (scanl (+) ((+) 2 2) [3]))
1 : (2 : (4 : (scanl (+) ((+) 4 3) [])))
1 : (2 : (4 : (7 : (scanl (+) 7 []))))
1 : (2 : (4 : (7 : [])))
我无法理解下面代码的计算,以及它是如何生成正确的斐波那契级数的

fibs = 1 : scanl (+) 1 fibs.
我发现非空列表(x:xs)的模式匹配如何适用于自引用列表很困难。
感谢您提供的帮助和任何资源,以便更好地理解自引用/无限列表

我们可以使用
1:
引起的相位差,仅使用
scanl
进行递归反向引用,如您在上一个示例中所示

let fib = 1 : scanl (+) 1 fib in take 5 fib
在本表中替换
scanl
的定义时,我们首先看到
(x:xs)
与现有的
匹配:

1 : 1 : scanl (+) 2 (drop 1 fibs)
此时,第二个元素存在,因此我们可以提取另一个
x

1 : 1 : 2 : scanl (+) 3 (drop 2 fibs)
1 : 1 : 2 : 3 : scanl (+) 5 (drop 3 fibs)
1 : 1 : 2 : 3 : 5 : scanl (+) 8 (drop 4 fibs)
我们并没有真正使用
拖放
,而是通过为每个元素匹配
,沿着我们正在构建的相同列表前进。我不得不给剩下的列表命名一些递归引用的内容,并找到
drop
表单来方便地表示生成和起源。实际上,像这样使用
drop
会导致整个列表保存在内存中,并且从一开始就不必要地遍历以查找下一个元素。事实上,我们只有一小块形状像递归
let
表达式的尾部,直到我们计算它:

fibsfrom a b = let morefibs = a : scanl (+) b morefibs in morefibs
如果使用1为该函数设定种子,或使用连续的一对斐波那契数为其设定种子,则可以获得整个列表。试试它,例如2 3或5 8。尾部的公式引用前面一个元素的列表,因此始终可以将其拆分为头部和尾部

有时,将引用视为图表会使事情更清楚。我们将递归视为一个循环,但仍然可以进行计算,因为我们只需要
标题列表
来执行下一步。这里是前几个步骤的graphviz点呈现(为迂回的“运行代码段-完整页面”方法道歉,堆栈溢出不能很好地处理点或svg)



fibsfibshead:tail11fibs-1Headscanl op init listfibs-scanltailscanl-FibsScanl-1nit++scanl-+opg1fibshead:tailg1fibs-G1Fibs-G1Fibs-HeadG1Fibs1 Tailg1Fibs1-g1 HeadG1ScanlScanl op init ListFibs1-g1++scanl-g1+Opg1FibsHedG2头:tailg1Fibs1-G1Fibs1-g1-G1Fibs1-g1-g1-g1-HeadG2:tailg1Fibs1-G1Fibs1-g1-g1-g1-g1-g1-g1-g1-g1头:tailg2fibs-g2fibs1 tailg2fibs1-g2\u 1headg2fibs2 head:tailg2fibs1-g2fibs2 tailg2\u 22g2fibs2-g2\u headg2扫描操作初始列表g2fibs2-g2scanltailg2scanl-g2fibs2列表g2++g2scanl g2+opg2\u 33g2scanl g2\u 3init
谢谢。我失去了自我参照清单的直觉。我不会说我完全理解这一点(在寻找解释时,我已经遇到了一些复杂的东西),但我的处境要好得多,至少我理解所问的情况。