I am a beginner with haskell and am reading the Learn you a haskell book. I have been trying to digest functors and applicative functors for a while now.
In the applicative functors topic, the instance implementation for Maybe is given as
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> something = fmap f something
So, as I understand it, we get Nothing if the left side functor (for <*>) is Nothing. To me, it seems to make more sense as
Nothing <*> something = something
So that this applicative functor has no effect. What is the usecase, if any for giving out Nothing?
Say, I have a Maybe String with me, whose value I don’t know. I have to give this Maybe to a third party function, but want its result to go through a few Maybe (a -> b)‘s first. If some of these functions are Nothing I’ll want them to silently return their input, not give out a Nothing, which is loss of data.
So, what is the thinking behind returning Nothing in the above instance?
How would that work? Here’s the type signature:
So the second argument here would be of type
Maybe a, while the result needs to be of typeMaybe b. You need some way to turnaintob, which you can only do if the first argument isn’tNothing.The only way something like this would work is if you have one or more values of type
Maybe (a -> a)and want to apply any that aren’tNothing. But that’s much too specific for the general definition of(<*>).Edit: Since it seems to be the
Maybe (a -> a)scenario you actually care about, here’s a couple examples of what you can do with a bunch of values of that type:Keeping all the functions and discard the
Nothings, then apply them:The
catMaybesfunction gives you a list containing only theJustvalues, then thefoldrcomposes them all together, starting from the identity function (which is what you’ll get if there are no functions to apply).Alternatively, you can take functions until finding a
Nothing, then bail out:This uses a similar idea as the above, except that when it finds
Nothingit ignores the rest of the list. If you like, you can also write it asapplyWhileJust = foldr (maybe (const id) (.)) idbut that’s a little harder to read…