As a newbie to Haskell I am trying to iterate a function (e.g., the logistic map) a large number of times. In an imperative language this would be a simple loop, however in Haskell I end up with stack overflow. Take for example this code:
main = print $ iter 1000000
f x = 4.0*x*(1.0-x)
iter :: Int -> Double
iter 0 = 0.3
iter n = f $ iter (n-1)
For a small number of iterations the code works, but for a million iterations I get a stack space overflow:
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
I cannot understand why this does happen. The tail recursion should be fine here.
Maybe the problem is lazy evaluation. I experimented with several ways to force strict evaluation, by inserting $! or seq at various positions, but with no success.
What would be the Haskell way to iterate a function a huge number of times?
I have tried suggestions from related posts: here or here, but I always ended up with stackoverflow for a large number of iterations, e.g., main = print $ iterate f 0.3 !! 1000000.
The problem is that your definition
tries to evaluate in the wrong direction. Unfolding it for a few steps, we obtain
and the entire call stack from
iter 1000000toiter 0has to be built before anything can be evaluated. It would be the same in a strict language. You have to organise it so that part of the evaluation can take place before recurring. The usual way is to have an accumulation parameter, likeThen adding strictness annotations – in case the compiler doesn’t already add them – will make it run smoothly without consuming stack.
The
iteratevariant has the same problem as youriter, only the call stack is built inside-out rather than outside-in as for yours. But sinceiteratebuilds its call-stack inside-out, a stricter version ofiterate(or a consumption pattern where earlier iterations are forced before) solves the problem,calculates
iterate' f 0.3 !! 1000000without problem.