我有一个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)
如果我定义一个MFunctor类Monad 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)
但是mmorph的hoist只有一个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)
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 a与Producer y m afrom 相同pipes,已经有一个MFunctor实例.