Max
Max

Reputation: 1877

Applicative functors. Type signatures of <*> and <$> in detail

We have signatures:

(<$>) :: Functor f     =>   (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b 

Let us play with it a bit:

(/)  <$> Just 5       <*> Just 2
=> Just 2.5

((/) <$> Just 5     ) <*> Just 2
=> Just 2.5

( Just (\x -> 5/x ) ) <*> Just 2
=> Just 2.5

Question:

((/) <$> Just 5) <*> Just 2
^^^^^^^^^^^^^^^^     @@@@@@

(<$>) :: Functor f     =>   (a -> b) -> f a -> f b
                                               ^^^
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
                          ^^^^^^^^^^    @@@

I interpret that ^^^ parts should match by their type. How come return type of <$> doesn't visually match input type of <*> in signatures?

What do I miss here? Thanks.

Upvotes: 3

Views: 190

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477608

It does match, but the f, a and b of the (<$>) and (<*>) function are variables, and the variables are different variables each time you use that function.

It therefore makes more sense to define the functions here as:

(<$>) :: Functor f     => (a -> b)   -> f a -> f b
(<*>) :: Applicative g => g (c -> d) -> g c -> g d

So that means that the ^ and @ indeed match like:

((/) <$> Just 5) <*> Just 2
^^^^^^^^^^^^^^^^     @@@@@@

(<$>) :: Functor f     => (a -> b)   -> f a -> f b
                                               ^^^
(<*>) :: Applicative g => g (c -> d) -> g c -> g d
                          ^^^^^^^^^^    @@@

So we know that the type of (/) <$> Just 5 is f b, and g (c -> d), whereas Just 2 has type g c. Since Just 2 has type Just 2 :: Num n => Maybe n, that thus means that g ~ Maybe and c ~ n (here x ~ y means x and y are the same type). Furthermore we can derive that f b ~ g (c -> d), so f ~ Maybe, and b ~ (c -> d).

We can furthermore analyze the (/) <$> Just 5 expression. We know that Just 5 has type Num m => Maybe m, so that means that a ~ m. The function (/) has type (/) :: Fractional k => k -> k -> k, so that means that a ~ b ~ k ~ m, and therefore we know that (/) <$> Just 5 has type (/) <$> Just 5 :: (Num m, Fractional m) => Maybe (m -> m), or less verbose (/) <$> Just 5 :: Fractional m => Maybe (m -> m) (a Fractional m implies Num m).

As we already found out b ~ (c -> d), so that means that m ~ c ~ d, and thus the type of the expression is: ((/) <$> Just 5) <*> Just 2 :: Fractional m => Maybe m.

Upvotes: 6

Related Questions