[redirecting to haskell-cafe]
On 3/1/07, Dave Tapley <dukedave at gmail.com> wrote:
> However this latter case gets stuck in an infinite loop, terminating on a stack overflow.
>> My question asks why this is the case, when laziness should ensure only the first 10 cases need to be computed.
>
You didn't say which function you had narrowed down the stack overflow
to, but I suspect it's here:
> firstTen :: IO [Int]
> firstTen = do
> infiniteNums <- iterateM addRand randNum
> return (take 10 infiniteNums)
In order for IO to work the way you'd expect, you have to be able to
specify which IO operations happen in what order, which is exactly
what a do-block within the IO monad specifies. But specifying the
order of operations also means specifying in what order evaluation
happens. So, the code you've written means "evaluate infiniteNums
fully (in order that we might do whatever IO operations it involves
before the return statement), then return the first 10 elements of its
result." Since you're forcing evaluation of an infinite list, the
program loops infinitely.
If you find this counter-intuitive, you wouldn't be the first, but
there's no other sensible interpretation for the code you've written.
Deferring evaluation of infiniteNums in this case would mean that IO
would happen in a strange and unpredictable order (or if it actually
wouldn't, then the compiler isn't smart enough to know that.)
I would solve this problem by writing a version of iterateM that takes
the length of the desired list as an argument (e.g., 10 in your
example), which sadly breaks modularity, but as I explained above,
working within the IO monad necessitates that. Someone more l33t than
me may be able to suggest a more elegant solution, though.
Cheers,
Kirsten
--
Kirsten Chevalier* chevalier at alum.wellesley.edu *Often in error, never in doubt
"They killed, they maimed, and they called information for numbers
they could easily look up in the book." -- Woody Allen