【问题标题】:Is there a principled way to compose two monad transformers if they are of different type, but their underlying monad is of the same type?如果它们的类型不同,但它们的底层 monad 类型相同,是否有一种原则方法可以组合两个 monad 转换器?
【发布时间】:2013-08-21 18:14:47
【问题描述】:

我无能为力来扩展这个问题。但这里有一个用例:假设你有两个 monad 转换器,ts,在同一个 monad m 上进行转换:

master :: (MonadTrans t, Monad m) => t m a b
slave  :: (MonadTrans t, Monad m) => s m a b

我想编写masterslave,这样当m 原语被提升为ts 时,它们可以相互通信。签名可能是:

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

一个用例,用糖化符号表示:

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

更新:sendreceivem 类型的原语。

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

【问题讨论】:

  • st 是任意的还是它们是特定的 - 我们是否试图创建这样的 st?同样的问题也适用于m - 它及其sendreceive 怎么样?
  • 是的 st 是任意的。 m 是我们在这里尝试创建的特定类型。 sendreceive 分别只是 (a,Bool) -&gt; m a bm a b 类型的原始函数。但它们是我给出的人为用例的附带条件,它们的实现细节并不重要。

标签: haskell monads monad-transformers


【解决方案1】:

是的。将 mmorph 包中的 hoistlift 结合使用:

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

要了解为什么会这样,请研究 hoist 的类型:

hoist :: (MFunctor t) => (forall x . m x -> n x) -> t m r -> t n r

hoist 允许您修改任何实现 MFunctor(其中大部分)的 monad 转换器的基本 monad。

bound 的代码所做的是让两个 monad 转换器就最终目标 monad 达成一致,在本例中为 t (s m)。嵌套ts 的顺序取决于你,所以我只是假设你想要t 在外面。

那么只需使用hoistlift 的各种组合来让两个子计算就最终的monad 堆栈达成一致。第一个是这样工作的:

master :: t m r
hoist lift master :: t (s m) r

第二个是这样的:

slave :: s m r
lift slave :: t (s m) r

现在他们都同意了,所以我们可以在同一个 do 块中对它们进行排序,它会“正常工作”。

要详细了解hoist 的工作原理,我建议您查看the documentation 以获取底部有a nice tutorialmmorph 包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    相关资源
    最近更新 更多