为什么MFunctor的"提升"没有"Monad n"约束?

Tom*_*lis 8 haskell

我有一个coroutine变压器

data Step y m a = Done a | Yield y (CoT y m a)

data CoT y m a = CoT (m (Step y m a))
Run Code Online (Sandbox Code Playgroud)

Monad实例

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))
Run Code Online (Sandbox Code Playgroud)

如果我定义一个MFunctorMonad m Monad n约束我可以定义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'))
Run Code Online (Sandbox Code Playgroud)

但是mmorphhoist只有一个Monad m约束.hoist没有它我可以定义我,还是缺乏一般性MFunctor

编辑:我发现它可能的!但我的问题仍然存在:我们确定这里不乏普遍性吗?

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'))
Run Code Online (Sandbox Code Playgroud)

Gab*_*lez 8

mmorph是在该pipes-3.*系列的背景下开发的(它曾经是一个内部pipes模块),其功能如下:

raise
    :: (Monad m, MFunctor t1, MonadTrans t2)
    => t1 m r -> t1 (t2 m) r
raise = hoist lift
Run Code Online (Sandbox Code Playgroud)

如果添加Monad n约束,hoist则必须添加Monad (t2 m)约束raise.我通常尝试最小化我的库中的约束,我找不到任何MFunctor需要Monad n约束的实例,所以我删除了它.

旁注:CoT y m aProducer y m afrom 相同pipes,已经有一个MFunctor实例.