
2010/8/9 Edward Z. Yang
Excerpts from Gábor Lehel's message of Mon Aug 09 15:39:49 -0400 2010:
Actually, while I haven't even used monad transformers before (just read about them a lot), I was thinking that something like this might be the way to solve the lift . lift . lift . lift . foo problem on the one hand, and by wrapping the 'contents' (e.g. the environment of a reader monad) of every level of the stack in a unique newtype (if the type isn't otherwise unique), the problem of "what if I want to use the same transformer more than once, how do I disambiguate them". (Do I have roughly the right idea?)
In fact, what you describe is already in use by current monad transformer libraries. :-) Take for example StateT in mtl [1]:
MonadWriter w m => MonadWriter w (StateT s m) MonadError e m => MonadError e (StateT s m) Monad m => MonadState s (StateT s m) MonadReader r m => MonadReader r (StateT s m) MonadTrans (StateT s) Monad m => Monad (StateT s m) Monad m => Functor (StateT s m) MonadFix m => MonadFix (StateT s m) MonadPlus m => MonadPlus (StateT s m) MonadIO m => MonadIO (StateT s m) MonadCont m => MonadCont (StateT s m)
By default, it comes with all of these instances, so that if you use a function that relies on say MonadReader and not Reader, no lifting is necessary. However, newtyping every reader monad because you want to use multiple copies of them isn't as good, because you still have to manually add all of these instances.
What I meant was to make certain that the 'r' in `ReaderT r m a`, say, is a unique type in every case, so that when you write `foo :: MonadReader SomethingOrOther m => m a -> m a` (for example), it's always unambiguous which MonadReader in the stack you might've meant. (If it's not... would you get an overlapping instances error, or what?)
Cheers, Edward
[1] http://hackage.haskell.org/packages/archive/mtl/1.1.0.2/doc/html/Control-Mon...
-- Work is punishment for failing to procrastinate effectively.