One of my struggles with lazy evaluation in Haskell is the difficulty of reasoning about memory usage. I think the ability to duplicate a thunk would make this much easier
Turn xs
into a function. This may be ugly, but works, because it prevents sharing:
let xs () = [1..1000000]
good = do
print $ foldl1' (+) (xs ())
print $ length (xs ())
I was wondering the same thing a while ago and created a prototypical implementation of such a thunk-duplication function. You can read about the result in my preprint „dup – Explicit un-sharing in haskell” and see the code at http://darcs.nomeata.de/ghc-dup. Unfortunately, the paper was neither accepted for the Haskell Symposium nor the Haskell Implementors Workshop this year.
To my knowledge, there is no real-world-ready solution to the problem; only fragile work-arounds as the unit parameter trick that might break due to one or the other compiler optimizations.
Interesting question. I don't know how to implement copyThunk
. But there is something else you can do (sorry if you already knew this):
xsFunction :: () -> [Int]
xsFunction = const [1..10000000]
better = do
print $ foldl1' (+) $ xsFunction ()
print $ length $ xsFunction ()
Here it definitely won't put the expression xsFunction ()
in a thunk, it will be calculated twice thus not making any memory bloat.
An interesting follow up on this is:
copyThunk
?