haskelltypestype-inferenceapplicativetype-signature

Understanding the type of (,) <$> length <*> head


I have this pair of functions

(,) <$> length :: Foldable t => t a -> b -> (Int, b)

and,

head :: [a] -> a

I would like to understand the type of

(,) <$> length <*> head

In (<*>) :: Applicative f => f (a -> b) -> f a -> f b type signature,

f :: (->) [a]

a :: b

b :: (Int -> b)

So, the instantiated type would be:

(->) [a] (Int, b)

However, I found out really its type is:

(->) [a] (Int, a)

Two questions, if I may:


Solution

  • Let's keep using the signature

    (,) <$> length :: Foldable t => t a -> b -> (Int, b)
    

    But change

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

    to

    (<*>) :: Applicative f => f (x -> y) -> f x -> f y
    

    so it doesn't get confusing. Clearly f ~ (->) [a] (assuming we're using the list instance of foldable) as you noticed, and thus x -> y ~ b -> (Int, b), so x ~ b and y ~ (Int, b). This is the part you missed, likely due to having confusing naming: the second argument is f x or [a] -> b, and you pass in head, which is [a] -> a. This forces b to become the same as a, otherwise the types wouldn't work out. The result is f y, or [a] -> (Int, b), except b is now a, giving you the [a] -> (Int, a) signature.