I am dealing with a library (ghcjs-dom) in which every function returns an IO (Maybe T).
I have a function a with returns an IO (Maybe x) and function b which takes x as an argument and returns an IO (Maybe y).
Is an operator that lets me do a ??? b and get an IO (Maybe y). My Hoogle search turned up nothing.
I am looking something like join that works for IO (Maybe (IO (Maybe t))) instead of IO (IO t) or Maybe (Maybe t).
From what I understand, you have:
a :: IO (Maybe X)
b :: X -> IO (Maybe Y)
There is a close relationship between IO (Maybe a) and MaybeT IO a, namely MaybeT converts one to the other:
MaybeT :: IO (Maybe a) -> MaybeT IO a
and the inverse operation is just runMaybeT:
runMaybeT :: MaybeT IO a -> IO (MaybeT a)
In the MaybeT monad the composition you want to perform is just the bind operation:
MaybeT a >>= (\x -> MaybeT (b x)) :: MaybeT IO Y
This results in a value of type MaybeT IO Y. To convert it back to a IO (Maybe Y) just use runMaybeT.
Update
Here is an operator to "compose" a and b:
andThen :: IO (Maybe a) -> (a -> IO (Maybe b)) -> IO (Maybe b)
andThen a b = runMaybeT $ MaybeT a >>= (\x -> MaybeT (b x) )
However, if you find yourself using this operator a lot, perhaps you
should rework your functions so you work primarily in the MaybeT IO
monad, and then you can just use >>= with a single runMaybeT
on the outside.
If you don't want to use MaybeT what you need is sequenceA or traverse from 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)
In your case f is IO and m Maybe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With