Simple Applicative Functor Example
applicative, functor, haskell
Solution
One method to approach this types of questions is to use substitution. Take the operator, in this case `(<*>)` or function, get its implementation and insert it to the code in question.
In the case of `(*) <$> (+3) <*> (*2) $ 2` you are using the `((->) a)` instance of `Applicative` found in the `Applicative` module in base, you can find the instance by clicking the source link on the right and searching for "(->":
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
Using the definition for `(<*>)` we can continue substituting:
((fmap (*) (+3)) <*> (*2)) 2 == (fmap (*) (+3)) 2 ((*2) 2)
== (fmap (*) (+3)) 2 4
Ok now we need the Functor instance for `((->) a)`. You can find this by going to the haddock info for `Functor`, here clicking on the source link on the right and searching for "(->" to find:
instance Functor ((->) r) where
fmap = (.)
Now continuing substituting:
(fmap (*) (+3)) 2 4 == ((*) . (+3)) 2 4
== (*) ((+3) 2) 4
== (*) 5 4
== 20
A more symbolic appraoch
Many people report better long term sucess with these types of problems when thinking about them symbolically. Instead of feeding the 2 value through the problem lets focus instead on `(*) <$> (+3) <*> (*2)` and only apply the 2 at the end.
(*) <$> (+3) <*> (*2)
== ((*) . (+3)) <*> (*2)
== (\x -> ((*) . (+3)) x ((*2) x))
== (\x -> ((*) . (+3)) x (x * 2))
== (\x -> (*) (x + 3) (x * 2))
== (\x -> (x + 3) * (x * 2))
== (\x -> 2 * x * x + 6 * x)
Ok now plug in 2 for x
2 * 2 * 2 + 6 * 2
8 + 12
20
Problem
I'm reading the Learn You a Haskell book. I'm struggling to understand this applicative functor code: ``` (*) <$> (+3) <*> (*2) $ 2 ``` This boils down to: (3+2) * (2*2) = 20 I don't follow how. I can expand the above into the less elegant but more explicit for newbie comprehension version: ``` ((fmap (*) (+3)) <*> (*2)) 2 ``` I understand the basics of the `<*>` operator. This makes perfect sense: ``` class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b ``` But I don't see how the command works? Any tips?