[Haskell-cafe] why does a foldr not have a space leak effect?

Ryan Ingram ryani.spam at gmail.com
Mon Jul 30 23:15:45 CEST 2012


The difference is that foldl *must* produce the entire list of thunks, even
if f is lazy in its first argument.

There's no foldl that can perform better given a sufficiently-lazy f; given

head = foldr go fail where
    go x y = x
    fail = error "head: empty list"

head [a,b,c,d]
= foldr go fail [a,b,c,d]
= go a (foldr go fail [b,c,d])
= a

you might think you can define

last = foldl go fail where
    go x y = y
    fail = error "last: empty list"

but this fails to be sufficiently lazy:

last [a,b,c,d]
= foldl go fail [a,b,c,d]
= foldl go (go fail a) [b,c,d]
= foldl go (go (go fail a) b) [c,d]
= foldl go (go (go (go fail a) b) c) [d]
= foldl go (go (go (go (go fail a) b) c) d) []
= go (go (go (go fail a) b) c) d
= d

which allocates lots of extra space for thunks, which may even take more
memory than the original list.

Whereas if last uses foldl':

last [a,b,c,d]
= foldl' go fail [a,b,c,d]
= let z = go fail a in seq z $ foldl' go z [b,c,d]
= foldl' go a [b,c,d]
= let z = go a b in seq z $ foldl' go z [c,d]
= foldl' go b [c,d]
= ...
= let z = go c d in seq z $ foldl' go z []
= foldl' go d []
= d

  -- ryan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120730/710edec0/attachment.htm>


More information about the Haskell-Cafe mailing list