[Haskell-cafe] Computing lazy and strict list operations at the same time

Brandon Moore brandonm at yahoo-inc.com
Wed Sep 27 03:38:22 EDT 2006


Andrew Pimlott wrote:
> This is a follow-up to a thread from June-July[1].  The question was how to
> write the function
>
>     initlast :: [a] -> ([a], a)
>     initlast xs = (init xs, last xs)
>
> so that it can be consumed in fixed space:
>
>     main = print $ case initlast [0..1000000000] of
>                      (init, last) -> (length init, last)
>
> Attempts were along the lines of
>
>     initlast :: [a] -> ([a], a)
>     initlast [x]    = ([], x)
>     initlast (x:xs) = let (init, last) = initlast xs
>                       in  (x:init, last)
>
> I seemed obvious to me at first (and for a long while) that ghc should
> force both computations in parallel; but finally at the hackathon
> (thanks to Simon Marlow) I realized I was expecting magic:  The elements
> of the pair are simply independent thunks, and there's no way to "partly
> force" the second (ie, last) without forcing it all the way.
According to the stuff about "selector thunks", it seems this should work

initlast [x] = ([],[x])
initlast (x:xs) =
let ~(init,last) = initlast xs
in (x:init, last)

It does, at least when I build with -ddump-simpl. Other builds, I get a 
program that overflows. Attached is a heap profile for a run with the 
main (10M rather than 100M as above - that just takes too long)

main = print $ case initlast [0..100000000]
of (init, last) -> (length init, last)

Brandon
-------------- next part --------------
A non-text attachment was scrubbed...
Name: a.out.ps
Type: application/postscript
Size: 20647 bytes
Desc: not available
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20060927/79ab0e88/a.out.ps


More information about the Haskell-Cafe mailing list