Haskell Fibonacci解释

时间:2014-11-10 12:10:34

标签: haskell functional-programming lazy-evaluation fibonacci thunk

我对Haskell很陌生,我试图围绕Fibonacci序列的惰性表达如何工作。

我知道之前已经问过这个问题,但是没有一个答案解决了我对结果进行可视化的问题。

代码是使用zipWith

的规范代码
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

我理解以下内容:

  1. zipWith字面上将两个列表拉在一起
  2. tail抓取列表中第一个元素
  3. Haskell引用' to-be'计算数据为thunks
  4. 根据我的理解,它首先使用[0,1,<thunk>]添加[1,<thunk>]zipWith (+)来提供[1,<thunk>]。所以现在你有了

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

    我用谷歌搜索过的很多参考资料都已进入&#34;可视化&#34;上面的行为

    fibs = 0 : 1 : 1 : zipWith (+) [1,1,<thunk>] ([1,<thunk>]).
    

    我的问题是:

    为什么上面一行中的 fibs 组件只对应 [1,1,<thunk>] 而不是 {{1 }

    不应该[0,1,1,<thunk>]包含整个列表加上fibs吗?

2 个答案:

答案 0 :(得分:11)

此中间步骤错误,因为zipWith已经处理了第一对项目:

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

回想一下zipWith在一般情况下的作用:

zipWith f (x:xs) (y:ys) = (f x y) : zipWith f xs ys

如果直接应用定义,则可以进行此扩展:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)                # fibs=[0,1,...]
     = 0 : 1 : zipWith (+) [0,1,...] (tail [0,1,...])      # tail fibs=[1,...]
     = 0 : 1 : zipWith (+) [0,1,...] [1,...]               # apply zipWith
     = 0 : 1 : (0+1 : zipWith (+) [1,0+1,...] [0+1,...])   
     = 0 : 1 : 1 : zipWith (+) [1,1,...] [1,...]           # apply zipWith
     = 0 : 1 : 1 : (1+1 : zipWith (+) [1,1+1,...] [1+1,...])
     = 0 : 1 : 1 : 2 : zipWith (+) [1,2,...] [2,...]       # apply zipWith
     = 0 : 1 : 1 : 2 : (1+2 : zipWith (+) [2,1+2,...] [1+2,...])
     = 0 : 1 : 1 : 2 : 3 : zipWith (+) [2,3...] [3,...]    # apply zipWith
     :

答案 1 :(得分:1)

如何看待正在发生的事情。

  1 1 2 3  5  8  13  <----fibs
  1 2 3 5  8 13      <----The tail of fibs
+________________    <----zipWith (+) function
  2 3 5 8 13 21      <----New fibs.  13 drops out --nothing to zip with

 finally, add [1, 1] to beginning
 1, 1, 2, 3, 5, 8, 13, 21