Bug in Control.Monad.State
Yitzchak Gale
gale at sefer.org
Tue Nov 22 17:48:40 EST 2005
Hi Udo,
> > Lack of laziness is also a serious problem
> > that a user cannot avoid. In my case, I have
> > to completely rewrite StateT, otherwise it is
> > totally unusable. This is definitely a bug.
> I disagree. If an operation is lazy, there is
> absolutely nothing you as a user can to to
> change that.
Right. Well, you can rewrite the library, or you
can restructure your entire app, but neither of
those are very good options.
> If an operation is too strict... you can always
> wrap the offending data in another constructor.
I have seen this claim several times, but I am
not yet convinced.
In my case, the unwanted strictness is coming from
the bind method of a monad from the standard
libraries. I don't see how to get rid of that
strictness by wrapping something in a constructor.
And even when it is possible to reduce strictness
by wrapping something - it means changing the
interface of existing functions. In a large
application, that could be a major disaster.
Here is an example. How would you fix this by
wrapping something in a constructor? No
restructuring is allowed (this is one function in
a large application, so changing the interface of
any function could have major consequences), and
no rewriting libraries is allowed.
You need to construct a random list of items. you
do not know in advance how many I will need; that
is determined by a stateful calculation as you
construct the items. Here is the function; it
diverges, unless you rewrite StateT with
strictness removed:
createItems :: RandomGen g => State g [Item]
createItems =
liftM catMaybes $ runListT $
flip evalStateT initialState $ runMaybeT $
do
item <- liftRandom $ repeatM randomItem
updateState item
needMoreItems >>= guard
return item
where
liftRandom = lift . lift . lift
Regards,
Yitz
More information about the Libraries
mailing list