如果两个monad变换器属于不同类型,但它们的底层monad是同一类型,是否有一种原则性的方法来组成它们?

chi*_*ro2 7 monads haskell monad-transformers

我无法解决这个问题.但是这里有一个用例:假设你有两个monad变换器,t并且s在同一个monad上进行转换m:

master :: (MonadTrans t, Monad m) => t m a b
slave  :: (MonadTrans t, Monad m) => s m a b
Run Code Online (Sandbox Code Playgroud)

而且我想要构建master并且slavem原语被提升到t和时它们可以相互通信s.签名可能是:

bound :: (MonadTrans t, MonadTrans s, Monad m, Monoid a) => t m a b -> s m a b -> (...)
But what is the type of (...) ?
Run Code Online (Sandbox Code Playgroud)

一个用例,用含糖表示法:

master :: Monoid a => a -> t m a b
master a = do 
   a <- lift . send $ (a,False)     -- * here master is passing function param to slave
   ...                              -- * do some logic with a
   b <- lift . send $ (mempty,True) -- * master terminates slave, and get back result

slave :: Monoid a => (a -> b) -> s m a b
slave g = do 
    (a,end) <- lift receive
    case end of 
        True -> get >>= \b -> exit b  
        _    -> (modify (++[g a])) >> slave g
Run Code Online (Sandbox Code Playgroud)

更新:send并且receive是类型的基元m.

我很抱歉,如果这个例子看起来很人为,或者过于类似协程,问题的精神真的与它无关,所以请忽略所有的相似之处.但主要的观点是monad之前ts不能相互合理地组合,但是在包装了一些潜在的monad之后m,它们现在可以组成并作为单个函数运行.至于组合函数的类型,我真的不确定,所以一些方向是值得赞赏的.现在,如果这种抽象已经存在,而我只是不知道它,那么那将是最好的.

Gab*_*lez 8

是.结合hoistmmorphlift要做到这一点:

bound
    :: (MonadTrans t, MonadTrans s, MFunctor t, Monad m)
    => t m () -> s m () -> t (s m) ()
bound master slave = do
    hoist lift master
    lift slave
Run Code Online (Sandbox Code Playgroud)

要了解其工作原理,请研究以下类型hoist:

hoist :: (MFunctor t) => (forall x . m x -> n x) -> t m r -> t n r
Run Code Online (Sandbox Code Playgroud)

hoist允许你修改任何实现的monad变换器的基本monad MFunctor(大多数是monad变换器).

代码的bound作用是使两个monad变换器在最终目标monad上达成一致,在这种情况下是t (s m).该顺序嵌套ts是你的,所以我只是假设你想t在外面.

然后,它只是一个使用的各种组合物hoist,并lift获得两个子计算到最后的单子堆栈上达成一致.第一个是这样的:

master :: t m r
hoist lift master :: t (s m) r
Run Code Online (Sandbox Code Playgroud)

第二个是这样的:

slave :: s m r
lift slave :: t (s m) r
Run Code Online (Sandbox Code Playgroud)

现在他们都同意所以我们可以在同一个do区块内对它们进行排序,它将"正常工作".

要了解有关hoist工作原理的更多信息,我建议您查看包含文档的文档,该文档底部mmorph一个很好的教程.