
On Thursday 09 June 2011, 18:41:40, Alexey Khudyakov wrote:
On 09.06.2011 20:09, Yves Parès wrote:
Is it not:
noLeak :: State Int () noLeak = do
a <- get
*>* *let a' = (a + 1)
a' `seq` put a'* noLeak
??
Indeed. Now I understand. It didn't work for me earlier because of different behavior of 'forever' in ghci and compiled code.
This function leaks in ghci and do not in compiled code without optimizations (with optimizations GHC is smart enough to make everything strict).
noLeak = forever $ do { a <- get; let a' = a+1; a' `seq` put a' }
Function with explicit recursion do not leak in both cases.
noLeak = do { a <- get; let a' = a+1; a' `seq` put a'; noLeak }
What causes this difference?
forever a = a >> forever a doesn't tie to itself without optimisations, so my guess is that it gets expanded when you run/eval/execState it in ghci, building the thunk a >> a >> a >> a >> ... If you define forever' a = let a' = a >> a' in a' the variant using forever' runs in constant space in ghci. This, like the explicit recursion, builds a cyclic structure, hence avoids the leak.