On Fri, 5 Jan 2007, Jeremy Shaw wrote:

Hi,

In this case, the stack overflow you are seeing is due to laziness not
tail recursion.

Aha.  I knew it was something stupid.


Because you never demand the value of any element in the list, Haskell
never bothers to calculate it. So you have a list that looks like:

[ i,  i - 1, (i - 1) - 1, ((i - 1) - 1 - 1), .. ]

So, by the time you get up to some big numbers, you have built up a
very large thunk. For some reason this is causing a stack overflow.


Actually, this makes sense to me. Recursively forcing lazy thunks is not tail recursive, it needs to allocate stack frames. So if a million-deep recursive thunk, forcing it is a problem.

The easiest solution is to make things a little more strict. For
example, if you change:

nth i (x:xs) = if i < 0 then Empty else nth (i-1) xs

to:

nth i (x:xs) = x `seq` (if i < 0 then Empty else nth (i-1) xs)

This will force x enough that things do not overflow.

j.

ps. just a warning, seq is not entirely straightforward to use, so
while it works in this case, it may not always work for you. I think
there might be a wiki page somewhere that explains how to avoid space
leaks in greater detail, but I can't seem to find it.

Another solution that does not involve using seq would be to replace
the above line with these two lines:

nth i (0:xs) = if i < 0 then Empty else nth (i-1) xs
This looks to be a typo, not sure if it's mine or yours. The definition I was playing with was (or should be):

nth i (x:xs) = if i < 0 then Empty else nth (i-1) xs

Brian

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to