
David Menendez wrote:
On Fri, Apr 23, 2010 at 3:46 PM, Dan Doel
wrote: Monad m and MonadTrans t do not imply Monad (t m), which is what that definition requires.
This works for me:
lift :: (MonadTrans t, Monad m, Monad (t m)) => m a -> t m a lift m = morph (\d -> m >>= d . return)
I think the point was that the current definition of lift does not have a Monad(t m) constraint and therefore the above definition doesn't suffice because it imposes additional requirements. (Granted they're desirable requirements, but all the same.) We don't actually need all of Monad(t m). The only thing we need is some general function: returnT :: (MonadTrans t, Monad m) => a -> t m a Though that's not possible, since t is held abstract and MonadTrans only offers to construct one if you can provide a function to destruct them. So alternatively, we could use morph to construct returnT if only we had the general function: -- where B is some type associated with the t. foo :: (MonadTrans t, Monad m) => t m a -> m B Which, of course, we can't do either since we don't even know which type B is (when t is held abstract). Thus, the only ways to define lift using morph are: (1) add a (Monad (t m)) constraint to morph (1') add an (Applicative (t m)) constraint to morph (1'') define a class for pointed functors and add (Pointed(t m)) (2) add the returnT function to the MonadTrans class (3) add an MPTC/associated type B and the function foo to the MonadTrans class (4) some similar hackery I've overlooked. -- Live well, ~wren