在在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(如第一个版本中那样)?
答案 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
作为第二个元素,依此类推。