我正在处理一个库(ghcjs-dom
),其中每个函数都返回一个IO (Maybe T)
。
我有一个函数a
,返回IO (Maybe x)
和函数b
,它将x
作为参数并返回IO (Maybe y)
。
是否允许我执行a ??? b
并获得IO (Maybe y)
的运算符。我的Hoogle搜索没有任何结果。
我看起来像join
,适用于IO (Maybe (IO (Maybe t)))
而不是IO (IO t)
或Maybe (Maybe t)
。
答案 0 :(得分:10)
根据我的理解,你有:
a :: IO (Maybe X)
b :: X -> IO (Maybe Y)
IO (Maybe a)
和MaybeT IO a
之间存在密切关系,即MaybeT
将一个转换为另一个:
MaybeT :: IO (Maybe a) -> MaybeT IO a
,反向操作只是runMaybeT
:
runMaybeT :: MaybeT IO a -> IO (MaybeT a)
在MaybeT monad中,你想要表演的作品就是 绑定操作:
MaybeT a >>= (\x -> MaybeT (b x)) :: MaybeT IO Y
这会产生MaybeT IO Y
类型的值。要将其转换回IO (Maybe Y)
,只需使用runMaybeT
。
<强>更新强>
以下是&#34;撰写&#34; a 和 b :
andThen :: IO (Maybe a) -> (a -> IO (Maybe b)) -> IO (Maybe b)
andThen a b = runMaybeT $ MaybeT a >>= (\x -> MaybeT (b x) )
但是,如果你发现自己经常使用这个操作符,也许你
应该修改你的功能,这样你才能主要在MaybeT IO
工作
monad,然后你只需使用>>=
一个runMaybeT
在外面。
答案 1 :(得分:3)
如果您不想使用MaybeT
,sequenceA
或traverse
来自Data.Traversable
。
Prelude Data.Traversable Control.Monad> :t fmap join . join . fmap sequenceA
fmap join . join . fmap sequenceA
:: (Traversable m, Control.Applicative.Applicative f, Monad m,
Monad f) =>
f (m (f (m a))) -> f (m a)
在你的情况下,f是IO,m可能。