Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't `iterate` from the Prelude tie the knot?

Why isn't iterate defined like

iterate :: (a -> a) -> a -> [a]
iterate f x = xs where xs = x : map f xs

in the Prelude?

like image 881
user3237465 Avatar asked Jun 20 '15 01:06

user3237465


2 Answers

Tying the knot like that doesn't appear to increase sharing.

Contrast with:

cycle xs = let x = xs ++ x in x

Tying the knot here has the effect of creating a circular linked list in memory. x is its own tail. There's a real gain.

Your suggested implementation doesn't increase sharing over the naive implementation. And there's no way for it to do so in the first place - there's no shared structure in something like iterate (+1) 0 anyway.

like image 101
Carl Avatar answered Oct 31 '22 16:10

Carl


There is no knot tying going on in your version, it just maintains a pointer one notch back on the produced list, to find the input value there for the next iteration. This means that each list cell can't be gc-ed until the next cell is produced.

By contrast, the Prelude's version uses iterate's call frame for that, and since it's needed only once, a good compiler could reuse that one frame and mutate the value in it, for more optimized operation overall (and list's cells are independent of each other in that case).

like image 6
Will Ness Avatar answered Oct 31 '22 17:10

Will Ness