Haskell 单子到单子

Haskell monad into monad

有方法(>>=) :: forall a b. m a -> (a -> m b) -> m b。 我如何制作方法 :: forall a b. m (n a) -> (a -> m (n b)) -> m (n b) 其中 m 和 n 是单子。

正如 PyRulez 所写,对此没有通用的解决方案,但鉴于您报告的类型,类似以下的方法应该有效。

你将需要

import Control.Monad (join)

使用 do 表示法,您可以组合两个函数,foobar,如下所示:

comp :: (a -> TargetClient (MethodResult b)) ->
        (b -> TargetClient (MethodResult c)) ->
         a -> TargetClient (MethodResult c)
comp foo bar x = do
  f <- foo x
  b <- join <$> traverse bar f
  return b

如果您不喜欢 do 符号,您可以将其全部简化为:

comp' :: (a -> TargetClient (MethodResult b)) ->
         (b -> TargetClient (MethodResult c)) ->
          a -> TargetClient (MethodResult c)
comp' foo bar x = foo x >>= fmap join . traverse bar

当您将 f 映射到 bar 时,您会得到单子堆叠的错误顺序,可以这么说,但是您可以使用 traverse 来切换堆叠。即使你这样做,你也会在 Either 中有一个 Either,所以这就是你需要 join.

的原因

如果 mn 都是 monad,则需要额外的一块来使复合 m.n 也成为 monad。

需要的是一个"distributive law",也就是自然态射 forall a . n(m a) -> m(n a)(见here出自Beck,也用于Street)

然后很容易编写缺失的部分并验证它是否满足 monad 法则。