In this example from Learn you a Haskell, the author showed how to declare an instance of Applicative
for function ->r
instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x -> f x (g x)
Later on, he gave a concrete example
ghci> (\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5
[8.0,10.0,2.5]
I try to reason this snippet step by step
(+3) <*> (*2) <*> (/2)
as f <*> g <*> h
and thinking that f <*> g <*> h
returns a function \x -> f x (g x (h x))
, I thought (+3) <*> (*2) <*> (/2)
returns a function \x -> x+3 (x*2 (x/2))
. But I can not do :t (+3) <*> (*2) <*> (/2)
in ghci, which raises this errorerror:
• Occurs check: cannot construct the infinite type:
a1 ~ a -> a1 -> b
Expected type: (a -> a1 -> b) -> a1
Actual type: a1 -> a1
• In the second argument of ‘(<*>)’, namely ‘(/ 2)’
In the expression: (+ 3) <*> (* 2) <*> (/ 2)
(+3) <*> (*2) <*> (/2)
does return a function \x -> x+3 (x*2 (x/2))
, how does it pattern match with the lambda function \x y z -> [x,y,z]
? (Actually I am still having some trouble to understand lambda functions except for the really basic simple ones.)I think you got the precedence wrong. The expression
(\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5
does not involve as a subexpression the one you mention
(+3) <*> (*2) <*> (/2)
since it should be parsed associating to the left, as follows:
((((\x y z -> [x,y,z]) <$> (+3)) <*> (*2)) <*> (/2)) $ 5
Here, we start to simplify from the left:
(\x y z -> [x,y,z]) <$> (+3)
= { def. <$> }
(\a y z -> [(+3) a,y,z])
Then, we proceed:
(\a y z -> [(+3) a,y,z]) <*> (*2)
= { def. <*> }
(\a z -> [(+3) a, (*2) a,z])
Finally,
(\a z -> [(+3) a, (*2) a,z]) <*> (/2)
= { def. <*> }
(\a -> [(+3) a, (*2) a, (/2) a])
As a last step, we let a
to be 5
, obtaining [5+3, 5*2, 5/2]
.