Why does MFunctor's 'hoist' not have 'Monad n' constraint?
haskell
Solution
`mmorph` was developed in the context of the `pipes-3.*` series (it used to be an internal `pipes` module), which had functions like this:
raise
:: (Monad m, MFunctor t1, MonadTrans t2)
=> t1 m r -> t1 (t2 m) r
raise = hoist lift
If you add the `Monad n` constraint to `hoist` then you have to add a `Monad (t2 m)` constraint to `raise`. I generally try to minimize constraints in my libraries and I couldn't find any `MFunctor` instances that needed the `Monad n` constraint, so I removed it.
Side note: `CoT y m a` is the same thing as `Producer y m a` from `pipes`, which already has an `MFunctor` instance.
Problem
I have a coroutine transformer ``` data Step y m a = Done a | Yield y (CoT y m a) data CoT y m a = CoT (m (Step y m a)) ``` with `Monad` instance ``` unCoT :: CoT y m a -> m (Step y m a) unCoT (CoT m) = m instance Monad m => Monad (CoT y m) where return = CoT . return . Done CoT x >>= f = CoT $ do x' <- x case x' of Done a -> unCoT (f a) Yield y x' -> return (Yield y (x' >>= f)) ``` If I define an `MFunctor` class with `Monad m` and `Monad n` constraints I can define `hoist` ``` class MFunctor t where hoist :: (Monad n, Monad m) => (forall a. m a -> n a) -> t m b -> t n b instance MFunctor (CoT y) where hoist f (CoT m) = CoT $ do step <- f m return (case step of Done x -> Done x Yield y m' -> Yield y (hoist f m')) ``` But `mmorph`'s `hoist` only has a `Monad m` constraint. Can I define my `hoist` without it, or is this a lack of generality of `MFunctor`? EDIT: I worked out it is possible! But my question still stands: are we sure there's no lack of generality here? ``` instance MFunctor (CoT y) where hoist f (CoT m) = CoT $ f $ do step <- m return (case step of Done x -> Done x Yield y m' -> Yield y (hoist f m')) ```