[英]Haskell monad into monad
有方法(>>=) :: forall a b. ma -> (a -> mb) -> mb
(>>=) :: forall a b. ma -> (a -> mb) -> mb
。 我该如何制作方法:: forall a b. m (na) -> (a -> m (nb)) -> m (nb)
:: forall a b. m (na) -> (a -> m (nb)) -> m (nb)
,其中m和n是单子。
正如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
用bar
映射f
时,可以说单子堆叠的顺序错误,但是可以使用traverse
切换堆叠。 即使这样做,您也会在Either
中拥有一个Either
,因此这就是您需要join
的原因。
如果m
和n
都是单子,则还需要另外一块使合成mn
成为单子。
所需要的是“分布定律”,即对所有a的自然态forall a . n(ma) -> m(na)
forall a . n(ma) -> m(na)
(请参阅此处,它来自Beck,也用于Street)
这样就很容易写出丢失的部分并验证其是否满足单子法则。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.