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
表示法,您可以组合两个函数,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
时,您会得到单子堆叠的错误顺序,可以这么说,但是您可以使用 traverse
来切换堆叠。即使你这样做,你也会在 Either
中有一个 Either
,所以这就是你需要 join
.
的原因
如果 m
和 n
都是 monad,则需要额外的一块来使复合 m.n
也成为 monad。
需要的是一个"distributive law",也就是自然态射
forall a . n(m a) -> m(n a)
(见here出自Beck,也用于Street)
然后很容易编写缺失的部分并验证它是否满足 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
表示法,您可以组合两个函数,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
时,您会得到单子堆叠的错误顺序,可以这么说,但是您可以使用 traverse
来切换堆叠。即使你这样做,你也会在 Either
中有一个 Either
,所以这就是你需要 join
.
如果 m
和 n
都是 monad,则需要额外的一块来使复合 m.n
也成为 monad。
需要的是一个"distributive law",也就是自然态射
forall a . n(m a) -> m(n a)
(见here出自Beck,也用于Street)
然后很容易编写缺失的部分并验证它是否满足 monad 法则。