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)
有一些签名功能:
Run Code Online (Sandbox Code Playgroud)a -> IO (m b) b -> IO (m c) c -> IO (m d)我如何将它们链接起来
Run Code Online (Sandbox Code Playgroud)a -> IO (m d)
一般来说,你可能无法做到.例如,如果m是Const,我不确定这是否有意义.一般来说,你可能期望m成为一个Monad.但是,请注意,即使m 是 a Monad,其组成IO也可能不是(见此).
Run Code Online (Sandbox Code Playgroud)Value1 -> IO (Maybe Value2) Value2 -> IO (Maybe Value3) Value3 -> IO (Maybe Value4)
啊,现在你在说话!你在这里寻找的抽象是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,rest2和rest3功能.正如已经在评论中指出的MaybeT IO a可以转换为IO (Maybe a)(实际上这正是做什么runMaybeT和MaybeT做).
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)