According to the Haskell 2010 language report, its type checker is based on Hindley-Milner. So consider a function f
of this type,
f :: forall a. [a] -> Int
It could be the length function for instance. According to Hindley-Milner, f []
type checks to Int
. We can prove this by instantiating the type of f
to [Int] -> Int
, and the type of []
to [Int]
, then conclude that the application ([Int] -> Int) [Int]
is of type Int
.
In this proof, I chose to instantiate types forall a. [a] -> Int
and forall a. [a]
by substituting Int
to a
. I can substitute Bool
instead, the proof works too. Isn't it strange in Hindley-Milner that we can apply a polymorphic type to another, without specifying which instances we use ?
More specifically, what in Haskell prevents me from using the type a
in the implementation of f
? I could imagine that f
is a function that equals 18
on any [Bool]
, and equals the usual length function on all other types of lists. In this case, would f []
be 18
or 0
? The Haskell report says "the kernel is not formally specified", so it's hard to tell.