评估循环列表中的where子句

时间:2017-02-17 03:33:22

标签: haskell recursion functional-programming

在Haskell中功能性思考(p 213)中,我们显示了两个版本的循环列表。一个人在二次时间内进行评估:

iterate3 f x = x:map f (iterate3 f x)

iterate3 (2*) 1
= 1:map (2*) (iterate3 (2*) 1)
= 1:2:map (2*) (map (2*) (iterate3 (2*) 1))
= 1:2:4:map (2*) (map (2*) (map (2*) (iterate3 (2*) 1)))

另一个使用where的人在线性时间内进行评估:

iterate2 f x = xs where xs = x:map f xs

iterate2 (2*) 1    
xs          where xs = 1:map (2*) xs
= 1:ys      where ys = map (2*) (1:ys)
= 1:2:zs    where zs = map (2*) (2:zs)
= 1:2:4:ts  where ts = map (2*) (4:ts)

我不太明白这个评价。如何将x重新分配给每个连续的列表元素,而不是1(如第一个版本中那样)?

2 个答案:

答案 0 :(得分:4)

重要的细节是xs中的iterate2是根据自身定义的,创建了一个循环结构。
(这有时被称为"打结"。)

将其可视化为图形,评估类似于此(警告:ASCII艺术)。

xs where xs = 1 : map (2*) xs

     :  <----------+
   /   \           | applies to
  1    map (2*)  --+

-->

     :
   /   \
  1     :  <--------+   
      /   \         | applies to
     2   map (2*) --+

-->

     :
   /   \
  1     : 
      /   \
     2     : <---------+
         /   \         | applies to
        4   map (2*) --+

等等。

答案 1 :(得分:1)

让我们在iterate2中展开递归:

xs = x : map f xs
   = x : map f (x : map f xs)                          -- Inline xs
   = x : (f x) : map f (map f xs)                      -- Definition of map
   = x : (f x) : map f (map f (x : map f xs))          -- Inline xs
   = x : (f x) : map f ((f x) : map f (map f xs))      -- Definition of map
   = x : (f x) : (f (f x)) : map f (map f (map f xs))) -- Definition of map
   ...

因此,您可以看到iterate2 f x返回的列表包含x作为第一个元素,f x作为第二个元素,依此类推。