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:
b
switched for an a
?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.