Reputation: 1517
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
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