Stacking up state transformers
Andrew J Bromage
ajb@spamcop.net
Wed, 5 Feb 2003 15:55:21 +1100
G'day.
On Tue, Feb 04, 2003 at 05:24:29PM -0000, Guest, Simon wrote:
> I can still access my backtracked state using Control.Monad.State.{get,put}, but
> I can't access my non-backtracked state.
Iavor mentioned using "lift", plus some other ideas. That's what
I'd do:
liftNondet = lift
liftOuterState = lift . lift
(Naturally I'd call these something more meaningful.)
As a matter of style, I generally advocate the philosophy that your
basic operations should be semantically meaningful, rather than
operationally meaningful. So, for example, rather than:
type FooM a = StateT Bar (StateT Baz IO) a
munch :: FooM ()
munch = do baz <- lift (lift get)
doStuffWith baz
I prefer:
type FooM a = StateT Bar (StateT Baz IO) a
getBaz :: FooM Baz
getBaz = lift (lift get)
munch :: FooM ()
munch = do baz <- getBaz
doStuffWith baz
Not only is it more readable, it's also more robust in the face of
change (e.g. when you decide to change to ReaderT instead).
In your case, it's a state monad you're trying to get at, and a state
monad only supports a few meaningful operations (get, put, modify, gets)
not all of which are generally useful for a given kind of state. I
think it makes more sense to specify a "public interface" for your
monad and use only that.
Cheers,
Andrew Bromage