
Hello all, the State Monad wraps around a computation s -> (s,a). Inside a do block I am actually assembling such a computation. Now when I do this many times, i.e. in a recursice call, I am builing a huge expression m a >>= (\a -> mb) >>= (\b -> mc) ... The result of this expression is a function s -> (s,a). But I cannot see how the space for this expression can be reclaimed, and how it could ever run in constant space. Once I call runState and I provide an initial s, I have some hope, but before? How is this supposed to work? How do I avoid allocating space for this huge expression?

Being an absolute beginner myself, I should probably refrain from trying to answer this one, but since no one else did, I’ll give it a shot: I assume it all comes down to laziness. The gargantuan expression will not be built all at once, but rather the beginning of it is built and evaluated. The result of evaluating the leftmost part will (hopefully) be simpler than the expression that defined it! In any case, that expression is now safely discarded, a bit more of the expression is built, and the evaluation can proceed. The principle shouldn’t be all that different from any tail recursive function application, really. – Harald On 12 June 2016 at 23:11:32, martin (martin.drautzburg@web.de(mailto:martin.drautzburg@web.de)) wrote:
Hello all,
the State Monad wraps around a computation s -> (s,a). Inside a do block I am actually assembling such a computation. Now when I do this many times, i.e. in a recursice call, I am builing a huge expression
m a >>= (\a -> mb) >>= (\b -> mc) ...
The result of this expression is a function s -> (s,a). But I cannot see how the space for this expression can be reclaimed, and how it could ever run in constant space. Once I call runState and I provide an initial s, I have some hope, but before?
How is this supposed to work? How do I avoid allocating space for this huge expression?

Remember that StateT (and by extension, State) is just a newtype wrapper.
Newtypes have no runtime cost. In this case it simply contains a
function. Constructing an expression full of binds against StateT before
supplying an argument via runStateT is no different than combining several
functions and supplying their argument later.
As far as memory usage is concerned, there is one caveat. The state
variable that is returned after every bind can build up thunks if it is
altered but not fully evaluated in any given step. This could lead to a
memory link as operations are tacked onto the state variable you supplied.
If you use Control.Monad.State.Strict, that variable will be evaluated
whether you use it or not, preventing laziness from building up thunks.
On Sun, Jun 12, 2016 at 5:11 PM, martin
Hello all,
the State Monad wraps around a computation s -> (s,a). Inside a do block I am actually assembling such a computation. Now when I do this many times, i.e. in a recursice call, I am builing a huge expression
m a >>= (\a -> mb) >>= (\b -> mc) ...
The result of this expression is a function s -> (s,a). But I cannot see how the space for this expression can be reclaimed, and how it could ever run in constant space. Once I call runState and I provide an initial s, I have some hope, but before?
How is this supposed to work? How do I avoid allocating space for this huge expression? _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (3)
-
David McBride
-
Harald Hanche-Olsen
-
martin