這是等式推理一個偉大的運動:
fibs2 = foldr buildFibs [] [1..]
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
foldr buildFibs [] [1..] =
buildFibs 1 (foldr buildFibs [] [2..]) =
buildFibs 1 (buildFibs 2 (foldr buildFibs [] [3..])) =
buildFibs 1 (buildFibs 2 (buildFibs 3 (foldr buildFibs [] [4..]))) =
...
我希望現在你可以看到這個問題:foldr
試圖返回之前遍歷整個列表。如果我們用foldl
代替,會發生什麼?
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
buildFibs' = flip buildFibs
foldl buildFibs' [] [1..] =
foldl buildFibs' (buildFibs 1 []) [2..] =
foldl buildFibs' [0] [2..] =
foldl buildFibs' (buildFibs 2 [0]) [3..] =
foldl buildFibs' [0,1] [3..] =
foldl buildFibs' (buildFibs 3 [0,1]) [4..] =
foldl buildFibs' (0+1 : [0,1]) [4..] =
foldl buildFibs' [1,0,1] [4..] =
foldl buildFibs' (buildFibs 4 [1,0,1]) [5..] =
foldl buildFibs' (1+0 : [1,0,1]) [5..] =
foldl buildFibs' [1,1,0,1] [5..] =
foldl buildFibs' (buildFibs 5 [1,1,0,1]) [6..] =
foldl buildFibs' [2,1,1,0,1] [6..] =
-- For brevity I'll speed up the substitution
foldl buildFibs' [3,2,1,1,0,1] [7..] =
foldl buildFibs' [5,3,2,1,1,0,1] [8..] =
foldl buildFibs' [8,5,3,2,1,1,0,1] [9..] =
...
所以,你可以看到你其實可以計算使用buildFibs
和foldl
的斐波那契數,但不幸的是你向後構建他們的無限列表,你將永遠無法在計算特定元素因爲foldl
永遠不會終止。你可以計算它們的有限數量:
> take 10 $ foldl buildFibs' [] [1..10]
[34,21,13,8,5,3,2,1,1,0]
看起來像你一直在'buildFibs'中添加列表頭部。你的清單是無限的,但方向錯誤= P – Mokosha