I am trying to figure out with lambda calculus why the function result of the following code
(,) <$> (+1) <*> (+1)
has type Num a => a -> (a, a) instead of Num a => a -> a -> (a, a)
This is what I have got, am I doing something horribly wrong or is <*> just wired this way?
( \x, y -> (,) x y ) <$> ( \x -> x + 1 ) <*> ( \x -> x + 1 )
-- fmap applies first
(\x y -> (,) ((+1) x) y ) <*> ( \x -> x + 1 ) -- substituted the lambda with (+1) for better clarity
-- then goes apply
( \x y -> (,) ((+1) x) ((+1) y) )
how do the parameters of the lambda unify and at what point?
Let's see types in your example:
Rhs of
(<$>)
and Rhs/Lhs of(<*>)
must be the Applicative Functor. Your functor isNum a => (->) a
(the monad Reader).So, what type will be after
(<$>)
application (Pseudo code):After
(<*>)
(Pseudo code):But
Num a => (->) a (a, a)
is equivalent withNum a => a -> (a, a)
.As @chi wrote at head, the implementation
(<*>)
for type(->) r
is:And, if you apply, you'll get: