3
votes

Many times I tried to understand Functor and Monad in Haskell, but I failed. This time when I reached at LYAH's Applicative Functor, and thought I understood Applicative typeclasses, but I had some doubt about Applicative instance implementation for Maybe:

instance Applicative Maybe where  
pure = Just  
Nothing <*> _ = Nothing  
(Just f) <*> something = fmap f something

For the last line of above snippet, my understanding as follows:

(1) Just f is appropriated to f (a->b) in (<*>) :: f (a -> b) -> f a -> f b of class definition of Applicative, and f is appropriated to (a->b)

(2) something is appropriated to f a.

my question is from (2), why there is not written like Just something or the like?

In the Functor instance implementation for Maybe, there is fmap f (Just x) = Just (f x) and Just x is appropriated to f a of fmap :: (a -> b) -> f a -> f b.

for verifying my understanding, I changed something into Just something:

instance Applicative Maybe where  
pure = Just  
Nothing <*> _ = Nothing  
(Just f) <*> (Just something) = fmap f (Just something)

under gchi, I tried

Just (+3) <*> Just 9 

and got the same result Just 12, but when I tried

Just (++"hahah") <*> Nothing` 

I got the error

*** Exception: Functor.hs:(88,3)-(89,60): Non-exhaustive patterns in function <*>

I don't know why or what things I miss?

2
(Just f) <*> something and (Just f) <*> (Just something) are not equivalent; something is just a variable and matches anything, including the constructor Nothing, while Just something will not match nothing. Your idea will work correctly if you have also have Just _ <*> Nothing = Nothing. However, this is 3 lines, and programmers are lazy, so why write something in 3 lines that can be written in 2?user2407038
@user2407038, "matches anything" you said means something included Just somthing?abelard2008
@user2407038 "so why write something in 3 lines that can be written in 2?" means the _ in line 2 can be replaced by something (of course I have tested it using something in line 2)? the reason for using _ is laziness?abelard2008
Yes, the pattern something will match Just x. _ is equally as lazy as just a variable. So Nothing <*> x = Nothing would behave exactly the same way. The purpose of _ is to communicate to readers of your program that that parameter is not used.user2407038
Well-written question, thanks for your effort :-)luqui

2 Answers

3
votes

(This is an extension of my comment and does not really answer the question)

This alternate definition is easier to grasp:

instance Applicative Maybe where  
    pure = Just  
    (Just f) <*> (Just x) = Just (f x)
    _        <*> _        = Nothing

I think you fell into the trap of interpreting too much out of the name something. I always try to name the variables f and x in the context of applicatives (in the context of <*>, to be precise), that's just what they are, a function and a value the function is applied to.

3
votes
instance Applicative Maybe where  
pure = Just  
Nothing <*> _ = Nothing  
(Just f) <*> (Just something) = fmap f (Just something)

We can see whats wrong just by looking at the patterns! The first will match anything whose first parameter is Nothing, but the second will only match if it is both Just .... Nothing matches Just f and Nothing. Just because the first parameter is not Nothing doesn't mean the second has to be. If you really wanted to be explicit, you could write _ <*> Nothing = Nothing above the last line.