Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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).

like image 382
michaelmesser Avatar asked Aug 02 '16 18:08

michaelmesser


2 Answers

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.

like image 163
ErikR Avatar answered Nov 16 '22 12:11

ErikR


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.

like image 21
mb14 Avatar answered Nov 16 '22 12:11

mb14