Computer Science 591i
Hindley-Milner Types

Hindley-Milner Type Algebras

The monomorphic type system considered above can be regarded as an applicative algebra. It proves quite difficult to extend the above definition to a combinatory model, but let's come at it from another direction.

Definition

A Hindley-Milner type expression is defined:

Definition

If is a type-expression, and is a map from type-variables to type expressions, then () is extended to operate on type-expressions If 1 = (2) for some , we say that 1 is an instance of 2.

Definition

Two type-expressions, which have no variables in common, are said to be unifiable if they have a common instance.

We can define an equivalence relation on type expressions. 1 and 2 are equivalent if there exist and ' for which 1 = ( 2) and also 2 = '( 1)

Or in other words, two type-expressions are equivalent if each is an instance of the other.

Lemma MGU1 (Robinson)

If two type-expressions 1,2 are unifiable, then there exists a most general unifier = mgu(1,2), with the property that

The most general unifier is unique up to equivalence.


Now let's define an applicative algebra on equivalence classes of type-expressions.

Definition

A Hindley-Milner Applicative Algebra has as its carrier set a set of Hindley-Milner type expression-classes, and as its application rule In the above definition, we may suppose that 1 and 1 have no variables in common (if not, we simply rename them).

Lemma TA1

The operation defined above is well-defined.

Proof

Immediate from the definition of equivalence.

Lemma MGU2

mgu(1, mgu(2, 3)) = mgu(mgu(2, 2),3)

Lemma TA2

If, in a type-algebra that contains at least one constant 0, we have a type expression that unifies with every expression, then = for some type-variable .

Proof

Suppose = , a type-constant. Then does not unify with for any type-variable .

Suppose = 1 2 Then does not unify with 0 So the only possiblity is that = , a type-variable.


Lemma TA3

If, in a Hindley-Milner Applicative Algebra with at least one constant, two type expressions 1 and 2 have the property that for any

then 1 and 2 are equivalent.

Proof

By induction on h the height of 1

Base Case

h=0.

Inductive Step

Suppose that for all type-expressions 1 of height h

implies that 1 and 2 are equivalent.

Consider 1 of height h + 1, and 2, supposing that

Now 1 must have the form 11 12, and since 1 unifies with itself, it unifies with 2. So 2 is either (a) a type-variable, or (b) it has the form 21 22. But, if it were a type-variable, it would unify with 0, which 1 doesn't, so we are left with possibility (b).

Now suppose ' unifies with 21. Then, for any type variable it is clear that ' unifies with 11 12 hence, by our supposition, ' unifies with 21 22 so that ' unifies with 21.

Conversely, any " which unifies with 21 also unifies with 11. Hence by the inductive hypothesis, 11 is equivalent to 21.

Similarly 12 is equivalent to 22. Hence 1 is equivalent to 2, establishing our result.


Lemma

The Hindley-Milner Applicative Algebra defined above is a combinatory algebra, with

Proof

Consider Thus K satisfies the required law.

Now consider

We may suppose that the variables of 1, 2 and 3 are distinct.

There are 2 cases.

Theorem

The Hindley-Milner Applicative Algebra defined above is a combinatory model with provided that it contains at least one type-constant.

Proof

We already know that we have a combinatory algebra.


Discussion

Any term which features self-application, for example (x x) must have the type-value , since if x had the type (1 2) we would require that a term unify with a proper sub-term, which is impossible.

In particular both Curry's and Turing's fixpoint combinators involve self-application, so both map to in the type-algebra. However the following lemma shows that the existence of a well-typed fixpoint operator is not ruled out.

Lemma

A Hindley-Milner Combinatory Model contains a fixpoint combinator, namely:

Proof

Thus establishing our result.

Type-inference

Can use the above results for the practical purpose of assuring the type correctness of a program in a functional language? It would appear that we have above an adequate specification. To avoid a combinatorial explosion of combinators we would have to make use of the S' combinator, with additional efficiency from the B and C combinators. The type associated with these combinators is derived from the others.

The let expression

One problem that needs to be resolved is the let expression. It is usual to regard
    let variable = expr1
    in expr2
    end
as being a sugared form of however from the type-theory point of view this equivalence doesn't hold for most functional languages, since if expr1 is parametrically polymorphic the variable is allowed to have different instances of the polymorphic type in every occurrence in the body of the let expression, but not in the body of the expression. Consider for example the following POP2000 fragment
    let m = map
    in
       length (m sin list1) + length (m hd list2)
    end
Here map has the polymorphic type (->) -> (List ) -> (List ), but the first occurrence of m has the instance
    (float -> float) -> (List float) -> (List float)
while the second has type
    ((List ) -> ) -> (List (List )) -> (List )
but if we consider the corresponding form:
    (( m.
       length (m sin list1) + length (m hd list2)
    ) map)
we have a problem that m is not, according to the usual rules, allowed to have different instances of a polymorphic type. We can
    (( m1.
       length (m1 sin list1) + length (m2 hd list2)
    ) map map)