In the following, the statement "`M` has type `A`"
(or equivalently, "`A` is a type of `M`"),
notation `|- M : A ` or simply `M : A`, stand for
"the statement `{} |- M : A` has a proof in the type system of Curry".
Note that the set of assumption must be empty.

(var) ---------------- x : A |- x : A (abs) ------------------ |- \x.x : A -> AWe can also prove that

(var) -------------------------- x : B -> B |- x : B -> B (abs) -------------------------------- |- \x.x : (B -> B) -> (B -> B)In a sense, however, the first type (

**Theorem** If a lambda term has a type, then
it has a principal type, unique modulo renaming.

We don't give a formal proof of this theorem, but we show
how to construct the principal type. Let us start with
the example of the term `\x.x`. Intuitively,
any proof of a type statement for `\x.x` must have the
following form:

(var) ---------------- A = B x : A |- x : B (abs) ---------------- C = A -> B |- \x.x : CThe equation

the principal type ofIf, on the contray, the generic proof cannot be built, or the equations are not solvable, thenMisA theta.

`[True]`, i.e.`\x\y.x`, has principal type`A -> B -> A`.`[False]`, i.e.`\x\y.y`, has principal type`A -> B -> B`.`[1]`, i.e.`\x\y.x y`, has principal type`(A -> B) -> A -> B`.

- To find a proof for
`|- M : A`, where`A`is a given type. This process is called*Type Checking*. - To derive a (principal)
type for
`M`, by constructing a proof and imposing the conditions as explained above. This process is called*Type Inference*.

(remember that- val f = fn x => x;

(whereval f = fn : 'a -> 'a

Intuitively, it was to be expected that
`\x.x x` has no type.
In fact, `x x` represents
the application of a generic function
`x` to itself.
Now, there are functions
for which it makes sense to
be applied to themselves (for instance
the identity function), but this is not
the case for all functions.

For the same reason, also the fixpoint operator
`Y` (see notes of Lecture 2)
has no type.

- Any type variable
`A` `A -> B`, for any distinct type variables`A`and`B``A -> A -> B`, for any distinct type variables`A`and`B`

the inhabited types are exactly the formulas which are valid in the intuitionistic propositional logicwhere

**Definition**
Given a set of variables Var, and a set of function symbols Fun
(possibly including constant symbols) the
first-order terms are defined by the following grammar:

Term ::= Var | Fun(Term,...,Term)

In the case of type expressions, we have only one binary function symbol
(represented in infix notation): the arrow `->`.

**Definition**
A substitution `theta` is any mapping
`theta : Var -> Term`.

A substitution `theta`
will be denoted by listing explicitly
the result of its application to every variable (usually
we are interested only in finite substitutions, i.e. substitutions
which affect only a finite number of variables).
We will use the notation `x |-> theta(x)`.

The application of a substitution `theta`
to a term `t`, denoted by
`t theta`, is the term
obtained from `t` by
replacing each variable `x` by
`theta(x)`.

The composition of two substitutions `sigma`
and `theta` is the substitution
`sigma theta` s.t. for every variable
`x`, `(sigma theta)(x) = (x sigma)theta`.

**Definition**
Given a set of equations on terms
`E = {t1 = u1, ... , tn = un}`,
a substitution `theta` is a *unifier*
(solution) for `E`
iff for each `i` we have that
`ti theta` is identical to
`ui theta`.
A substitution `theta` is the
*most general unifier* of `E`
if it is a unifier for `E`
and, for any other unifier `sigma`,
there exists `sigma'` s.t.
`sigma = theta sigma'` (i.e.
`sigma` can be obtained by
instantiating `theta`).

**Example**
Consider the set of equations

We have thatE = {A = B->C , B->C = C->B}

`theta = {A |-> B->B , C |-> B}`is a unifier of`E`.`theta' = {A |-> B->C , C |-> B}`is**not**a unifier of`E`(the substitution must be applied simultaneously to all the eauatign3).`sigma = {A |-> (D->D)->(D->D) , B |-> D->D , C |-> D->D}`is also a unifier of`E`.`theta`is more general than`sigma`; in fact,`sigma = theta {B |-> D->D}`.