
Hi Yitz, I was thinking along the lines of a class linking the monad transformer with the base monad: class (MonadTrans mt, Monad b) => MonadTForm mt b | mt -> b where hoist :: (Monad m) => b a -> mt m a This is to restrict it directly between the base monad and the transformed version. If you wish to 'adapt' any other pair of monads, then I think that's another operation, just as lift is a different operation to hoist. Matthew On Sunday 23 March 2008, Yitzchak Gale wrote:
You are correct. This is a fundamental operation. It exists for just about every monad, but in a haphazard and inconsistent way. In my opinion, its type needs to be more polymorphic in a slightly different direction than what you are suggesting.
...
What I do sorely feel the need for is a "hoist" for each pair of base/transformer monads: i.e., polymorphic monad constructors.
So, for example, if we had
mkState :: (st -> (a, st)) -> m a
as a member of the MonadState st m class, then it would be so much easier to write functions
f :: MonadState st m => ...
that could be used without having to refactor it every time the monad stack changes. In general, each monad Foo would have a MonadFoo class (even the monads that don't have one yet) containing (at least) a mkFoo method that lifts the "underlying structure" polymorphically either to Foo or to FooT.
...
Regards, Yitz