如何链接 - > IO(mb)函数

Yur*_*hov 1 monads haskell types

有一些签名功能:

a -> IO (m b)
b -> IO (m c)
c -> IO (m d)
Run Code Online (Sandbox Code Playgroud)

我如何将它们链接起来

a -> IO (m d)
Run Code Online (Sandbox Code Playgroud)

实际应用:说有一组REST端点.返回值和下一个值都需要将previous返回的值作为参数.

因此从端点获取的函数如下:

Value1 -> IO (Maybe Value2)
Value2 -> IO (Maybe Value3)
Value3 -> IO (Maybe Value4)
Run Code Online (Sandbox Code Playgroud)

Ale*_*lec 6

有一些签名功能:

a -> IO (m b)
b -> IO (m c)
c -> IO (m d)
Run Code Online (Sandbox Code Playgroud)

我如何将它们链接起来

a -> IO (m d)
Run Code Online (Sandbox Code Playgroud)

一般来说,你可能无法做到.例如,如果mConst,我不确定这是否有意义.一般来说,你可能期望m成为一个Monad.但是,请注意,即使m a Monad,其组成IO也可能不是(见此).

Value1 -> IO (Maybe Value2)
Value2 -> IO (Maybe Value3)
Value3 -> IO (Maybe Value4)
Run Code Online (Sandbox Code Playgroud)

啊,现在你在说话!你在这里寻找的抽象是MaybeT和Kleisli的组合(>=>).然后,例如,

import Control.Monad ((>=>))
import Control.Monad.Trans.Maybe (MaybeT(..))

rest1 :: Value1 -> IO (Maybe Value2)
rest2 :: Value2 -> IO (Maybe Value3)
rest3 :: Value3 -> IO (Maybe Value4)

rest4 :: Value1 -> IO (Maybe Value4)
rest4 x = runMaybeT ((MaybeT . rest1 >=> MaybeT . rest2 >=> MaybeT . rest3) x)
Run Code Online (Sandbox Code Playgroud)

这仍然看起来有点难看.要做的事情是可能重构你的rest1,rest2rest3功能.正如已经在评论中指出的MaybeT IO a可以转换为IO (Maybe a)(实际上这正是做什么runMaybeTMaybeT做).

import Control.Monad ((>=>))
import Control.Monad.Trans.Maybe (MaybeT(..))

rest1 :: Value1 -> MaybeT IO Value2
rest2 :: Value2 -> MaybeT IO Value3
rest3 :: Value3 -> MaybeT IO Value4

rest4 :: Value1 -> MaybeT IO Value4
rest4 = rest1 >=> rest2 >=> rest3
Run Code Online (Sandbox Code Playgroud)