简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM