如何处理 IO (Maybe (IO (Maybe t))) 类型?

How to deal with an IO (Maybe (IO (Maybe t))) type?

我正在处理一个库 (ghcjs-dom),其中每个函数 returns 一个 IO (Maybe T)

我有一个函数 a 和 returns 一个 IO (Maybe x) 和函数 bx 作为参数和 returns 一个IO (Maybe y).

是一个运算符,可以让我执行 a ??? b 并获得 IO (Maybe y)。我的 Hoogle 搜索一无所获。

我正在寻找类似 join 的东西,它适用于 IO (Maybe (IO (Maybe t))) 而不是 IO (IO t)Maybe (Maybe t)

据我了解,您有:

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.

更新

这里是 "compose" ab 的运算符:

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 在外面。

如果您不想使用 MaybeT,您需要 sequenceAtraverse 来自 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 可能。