A powerful feature of Haskell is the automatic type inference of expressions. In the next few lectures, we will attempt to give an idea of how the type inference algorithm works. Ofcourse giving the type inference algorithm for the entire Haskell language is beyond the scope of this lecture so we take a toy example. Our aim is to give a complete type inference algorithm for an enriched version of lambda calculus, that has facilities to do integer arithmetic. Therefore, our lambda calulus expressions have, besides the other stuff we have seen, integer constants and the built in function '+'. We limit ourselves to only one operator because it is straight forward to extend our algorithm to work with other operation
The syntax is given below. Here and stands for arbitrary variable and , stands for arbitrary expressions.
We will write the lambda calculus expression in its infix form for ease of readability.
The haskell datatype that captures our enriched lambda calculus expression is the following
1 |
|
Clearly stuff like A (C 2) (C 3)
are invalid expressions but we ignore this for time being. One thing that the type checker can do for us is to catch such stuff.
We now want to assign types to the enriched lambda calculus that we have. As far as we are concerned the types for us are
Here is an arbitrary type variable. Again, we capture it in a Haskell datatype.
1 |
|
We will follow the following convention when dealing with type inference. The lambda calculus expressions will be denoted by Latin letters , , etc with appropriate subscripts. We will reserve the Latin letters , , and for lambda calculus variables. Types will be represented by the Greek letter and with the letters and reserved for type variables.
The notion of type specialisation is intuitivly clear. The type is a more general type than . We use to denote the fact that is specialisation of . How do we formalise this notion of specialisation ? Firstly note that any constant type like for example integer cannot be specialised further. Secondly notice that a variable can be specialised to a type as long as does not have an occurance of in it. We will denote a variable specialisation by . When we have a set of variable specialisation we have to ensure that there is no cyclicity indirectly. We doe this as follows. We say a sequence is a consistent set of specialisation if for each , does not contain any of the variables , . Now we can define what a specialisation is. Given a consistent sequence of specialisation let denote the type obtained by substituting for variables in with their specialisations in . Then we say that if there is a specialisation such that . The specialisation order gives a way to compare two types. It is not a partial order but can be converted to one by appropriate quotienting. We say two types are isomorphic, denoted by if and . It can be shown that forms an equivalence relation on types. Let denote the equivalence class associated with then, it can be show that is a partial order on .
Recall that the value of a closed lambda calculus expression, i.e. a lambda calculus expression with no free variables, is completely determined. More generally, given an expression , its value depends only on the free variables in it. Similary the type of an expression is completely specified once all its free variables are assigned types. A type environment is an assignment of types to variables. So the general task is to infer the type of a lambda calculus expression in a given type environment where all the free varaibles of have been assigned types. We will denote the type environments with with capital Greek letter with appropriate subscripts if required. Some notations that we use is the following.
We write to denote that the variable has been assigned the type .
For a variable , we use to denote the type that the type environment assigns to .
We write if assigned a type for the variable .
The type environment denotes the the type environment such that if and otherwise, i.e. the second type environment has a precedence.
As we described before, given a type environment , the types of any lambda calculus expression whose free variables are assigned types in can be infered. We use the notation to say that under the type environment one can infer the type for .
The type inference is like theorem proving: Think of infering as proving that the expression has type . Such an inference requires a set of rules which for us will be the type inference rules. We express this inference rules in the following notation
The type inference rules that we have are the following
Rule Const : where is an arbitrary integer.
Rule Plus :
Rule Var :
Rule Apply :
Rule Lambda :
Rule Specialise :
The goal of the type inference algorithm is to infer the most general type, i.e. Given an type environment and an expression find the type that satisfies the following two conditions
and,
If then .
Show that the specialisation order defined on types is a pre-order.
Given any pre-oder define the associated relation as if and . Prove that is an equivalence class. Show that can be converted into a natural partial order on the equivalence class of .