Reite's answer is correct, and I usually recommend processing it, however it seems to me that you do not quite understand how to work with Maybe values; if so, now it makes little sense to consider applicative functors.
The definition of Maybe is basically simple
data Maybe a = Nothing | Just a
This basically means that it sounds when you read it in plain English. "The value of type Maybe a is the Nothing value for this type or the value of the form Just a ."
Now you can use pattern matching to work with it, with example lists:
maybeReverse :: Maybe [a] -> Maybe [a] maybeReverse Nothing = Nothing maybeReverse (Just xs) = Just $ reverse xs
Basically, it means "If the value is Nothing , then there is nothing that could be undone, so the result will be Nothing again. If the value is Just xs , we can reverse xs and wrap it with Just again to turn it into Maybe [a] ).
Of course, such write functions for every single function that we ever wanted to use with the Maybe value would be tedious; Thus, a higher order acts for salvation! The observation here is that in maybeReverse we did nothing with reverse , we just applied it to the contained value and wrapped the result of it in Just .
So we can write a liftToMaybe function that does this for us:
liftToMaybe :: (a->b) -> Maybe a -> Maybe b liftToMaybe f Nothing = Nothing liftToMaybe f (Just a) = Just $ fa
A further observation we can make is that since functions are values, we can also have values ββof Maybe functions. In order to do something useful with those that we could deploy them again ... or notice that we are in the same situation as in the last paragraph, and we immediately notice that we donβt care what function is in this Maybe value and just write the abstraction directly:
maybeApply :: Maybe (a->b) -> Maybe a -> Maybe b maybeApply Nothing _ = Nothing maybeApply _ Nothing = Nothing maybeApply (Just f) (Just a) = Just $ fa
That, using our liftToMaybe function above, we can simplify things a bit:
maybeApply :: Maybe (a->b) -> Maybe a -> Maybe b maybeApply Nothing _ = Nothing maybeApply (Just f) x = liftToMaybe fx
The <$> and <*> statements in Reite's answer are basically just infix names for liftToMaybe (which is also known as fmap ) and maybeApply respectively; They have types
(<$>) :: Functor f => (a->b) -> fa -> fb (<*>) :: Applicative f => f (a->b) -> fa -> fb
You really don't need to know what is happening with Functor and Applicative objects (although you should take a look at them at some point: they basically generalize the Maybe functions above to other kinds of "context") - basically, just replace f with Maybe , and you will see that these are basically the same functions that we talked about earlier.
Now, I leave applying this to your original problem of multiplication to you (although other answers seem to spoil it).