
Thanks to Andrew, I'm now backtracking my state correctly. Now what I want to do is have two elements of state, an element that gets backtracked, and an element that doesn't. My monad now looks like this: type NondetState bs ns a = StateT bs (NondetT (StateT ns Maybe)) a where bs is my backtracked state, and ns my non-backtracked state. I can still access my backtracked state using Control.Monad.State.{get,put}, but I can't access my non-backtracked state. How do I burrow through the stack of monad transformers to get and put the 'ns' state? Supplementary question: What documentation should I be reading? cheers, Simon

hello, Guest, Simon wrote:
...
Now what I want to do is have two elements of state, an element that gets backtracked, and an element that doesn't.
My monad now looks like this:
type NondetState bs ns a = StateT bs (NondetT (StateT ns Maybe)) a
where bs is my backtracked state, and ns my non-backtracked state.
I can still access my backtracked state using Control.Monad.State.{get,put}, but I can't access my non-backtracked state. How do I burrow through the stack of monad transformers to get and put the 'ns' state?
Supplementary question: What documentation should I be reading? unfortunatelly there isn't much documentation. there are some useful
you can use the "lift" method. that however can get pretty cumbersome. an alternative way to deal with multiple transformers of the same type (i.e. many states, environments, or output) is to parameterize the transformer operations by an inedx specifying *which* state (environemnt, etc) you want to access, or update. the indexes are basically just used for their types, and one hopes that can be optimized away, i wonder if GHC can do it... the parameterization can be done (reasonably) nicely with Haskell's class system. for an implementation you can take a look at: www.cse.ogi.edu/~diatchki/MonadTransformers i use the library quite regularly and it seems to work pretty well. papers about monad transformers, one that comes to mind is "Monad Transformers and Modular Interpreters" by Sheng Liang, Paul Hudak, and Mark P. Jones hope this helped bye iavor -- ================================================== | Iavor S. Diatchki, Ph.D. student | | Department of Computer Science and Engineering | | School of OGI at OHSU | | http://www.cse.ogi.edu/~diatchki | ==================================================

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
participants (3)
-
Andrew J Bromage
-
Guest, Simon
-
Iavor S. Diatchki