timothyylim
timothyylim

Reputation: 1517

Handle nested Maybes [Haskell]

I have a function that requires the handling of two Maybes. This is an extremely naive implementation:

go :: IO (Maybe Int)
go = do
    res1 <- firstFunction
    case res1 of
      Nothing -> return Nothing
      Just a  -> do
        res2 <- secondFunction a
          case res2 of
            Nothing -> return Nothing
            Just b  -> return b

How could I structure this so that I can use the result a of the firstFunction in my secondFunction?

Upvotes: 1

Views: 162

Answers (1)

Daniel Wagner
Daniel Wagner

Reputation: 152682

Use MaybeT IO a instead of IO (Maybe a). Then:

firstFunction :: MaybeT IO X
firstFunction = undefined -- ...
secondFunction :: X -> MaybeT IO Int
secondFunction = undefined -- ...

go :: IO (Maybe Int)
go = do
    a <- firstFunction
    secondFunction a

-- OR

go = firstFunction >>= secondFunction

You may use these two halves of an isomorphism to convert between the two types:

MaybeT :: IO (Maybe a) -> MaybeT IO a
runMaybeT :: MaybeT IO a -> IO (Maybe a)

To reduce the total number of uses of them, I recommend pushing the former as deep into the leaves of your computation as you can, and lifting the latter as far out as you can. You may also like these actions for defining leaf computations:

lift :: IO a -> MaybeT IO a
liftIO :: IO a -> MaybeT IO a
empty :: MaybeT IO a -- for when you want a Nothing
pure :: a -> MaybeT IO a -- for when you want a Just
maybe empty pure :: Maybe a -> MaybeT IO a

Upvotes: 3

Related Questions