方法(>>=) :: 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是monad。
答案 0 :(得分:0)
正如PyRulez所写,对此没有通用的解决方案,但鉴于您报告的类型,以下内容应该有效。
你需要
import Control.Monad (join)
使用do
表示法,您可以撰写两个函数foo
和bar
,如下所示:
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
时,您将会以错误的顺序堆叠monad,可以这么说,但您可以使用traverse
来切换堆栈。即使你这样做,Either
中也会有一个Either
,这就是你需要join
的原因。
答案 1 :(得分:0)
如果m
和n
都是monad,那么您还需要一个额外的部分来使复合m.n
成为monad。
所需要的是一种“分配法则”,即一种自然的态射
forall a . n(m a) -> m(n a)
(请参阅here它来自Beck,也用于街道)
然后很容易编写缺失的部分并验证它是否符合monad法则。