> As I say, every time I've tried to do this, I end up writing a function to
> "run this stuff", and it typically takes a few hours to reach the point
> where it type-checks.

It took me a while the first time, but then I just learned the pattern
and I do it that way every time.  Here's my pattern:

type SomethingStack m = Monad1T Args (Monad2T Args (Monad3T Args m))
newtype SomethingT m a = SomethingT (SomethingStack m a)
  deriving (Functor, Monad, MonadIO, MonadError MyError, KitchenSink)
run_something_t (SomethingT m) = m

run :: (Monad m) => SomethingT m a -> m (a, MonadCrap, MonadCrap, ...)
run = Monad3T.run args . Monad2T.run args . Monad1T.run args . run_something_t

Or if you don't need the polymorphism, just stick a
'Identity.runIdentity' before Monad3T.run and make a

type Something = SomethingT Identity

The tricky bit is that you run them inside-out so the composition
looks like the stack backwards.  And sometimes mtl's 'run' functions
have an inconvenient arg order (e.g. StateT), so you have to flip
them.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to