为什么不从Prelude"迭代"打结?

use*_*465 8 haskell tying-the-knot

为什么没有iterate定义为

iterate :: (a -> a) -> a -> [a]
iterate f x = xs where xs = x : map f xs
Run Code Online (Sandbox Code Playgroud)

在序曲?

Car*_*arl 11

像那样打结似乎不会增加分享.

对比:

cycle xs = let x = xs ++ x in x
Run Code Online (Sandbox Code Playgroud)

在这里打结可以在内存中创建循环链表. x是它自己的尾巴.有一个真正的收获.

您建议的实现不会增加对天真实现的共享.首先,它没有办法实现这一点 - iterate (+1) 0无论如何都没有共享结构.

  • @ user3237465是的,`iterate(0 :) []`分享尾巴.但这与打结无关.这只是因为在`iterate fx = x:iterate f(fx)`中,变量`x`在两次使用之间共享. (2认同)

Wil*_*ess 6

在您的版本中没有打结,它只是在生成的列表上保留一个指针,在那里找到下一次迭代的输入值.这意味着在生成下一个单元格之前,不能对每个列表单元格进行格式化.

相比之下,Prelude的版本使用了它iterate的调用框架,并且因为它只需要一次,一个好的编译器可以重用那一帧并改变其中的值,以便更加优化整体操作(并且列表的单元格彼此独立)在这种情况下).