I can see that there's a lot of questions asking about the Maybe type and composition here, but I'm quite stuck and reading these has my head hurting, if I'm being quite honest.
Here's my situation:
Say, for the sake of example, I have a function:
addm a b = Just (a + b)
How can I create a function add :: Maybe Int -> Maybe Int -> Maybe Int
using the addm
function without using pattern matching to unwrap the Maybe
s?
I have tried something like
add x y = (addm <$> x) <*> y
but this has a type of Maybe Int -> Maybe Int -> Maybe (Maybe Int)
I'd also like to avoid using anything outside of the standard library if possible.
Edit: In my specific case, I actually only needed a function Maybe Int -> Int -> Maybe Int
so I was able to use
add x y = x >>= addm y
which did the trick. I'm stil curious about the answer to the original question, though.
There are a number of ways to write this. All involve the fact that Maybe
is a Monad.
Perhaps the easiest way to understand is to use the join function, which, for any Monad, removes the outermost level of nesting. Here it has type Maybe (Maybe a) -> Maybe a
, which is exactly what you are looking for, in combination with standard Applicative operators:
add ma mb = join $ addm <$> ma <*> mb
Or you can use do
notation to write the computation in a more imperative style, with what look like variable assignments, in which the Monad takes care of propagating any Nothing
values:
add ma mb = do
a <- ma
b <- mb
addm a b
Or you could explicitly use the "bind" (>>=
) operator, which is what the do
block above desugars to (but I find this less explicit and understandable than the other two options):
add ma mb = ma >>= \a -> mb >>= \b -> addm a b