Running out of memory in a simple monad
Zdenek Dvorak
rakdver@hotmail.com
Fri, 29 Nov 2002 13:53:45 +0000
Hello,
I hope I understand what's going on; if not please someone correct me.
>I have problems with monads and memory. I have a monad through which
>I thread output. If I do the concatenation of the output-strings in
>one way Hugs runs out of memory, but if I do it in another way
>everything works. I can't see why the first way doesn't work but the
>second is OK. I woudl appreciate if someone could tell me what I am
>doing wrong.
> Here is the non-working monad: -}
The problem is not directly connected to monads; what is the problem:
[] ++ x = x
(h:t) ++ x = h : (t++x),
i.e. time complexity of ++ is proportional to the length of first list.
first way:
>putCharM c = M $ \o -> ((), o ++ [c]) -- Is this stupid in some way?
this takes list (looong) of everything produced before this putCharM and
concatenates c as last member; this takes time linear in the length of
the list, summing over all putCharMs it is quadratic (and of course,
due to laziness a lot of memory is consumed; seq does not help, as it only
evaluates first cell of the list so that it sees it is not empty; deepSeq
would solve this, but the time consumption would still stay long).
the second way:
> M f >>= k = M $
> let (x, o) = f
> M f2 = k x
> (x', o') = f2
> in (x', o ++ o')
this is done reverse way (because >>= is bracketed to the right); we
concatenate output of f (short) with output of f2 (the rest of computation,
i.e. looong); but the time is proportional to the length of first list,
so it is constant in our case; summing it over all putCharMs, we get linear
time and we are happy :-)
If you want to do it the first way, define
putCharM c = M $ \o -> ((), c : o)
and then reverse the list in runM.
Zdenek Dvorak
_________________________________________________________________
Add photos to your messages with MSN 8. Get 2 months FREE*.
http://join.msn.com/?page=features/featuredemail