• No results found

The Curry Howard Isomorphism

This section forms the heart of our development of type theory. In it we look at a remarkable correspondence, or isomorphism, linking the typed lambda calculus and constructive logic. It has become known as the Curry Howard Isomorphism, in tribute to Haskell B. Curry and W. Howard who were among those first to observe it [CF58, How80]. Others include Scott, Lauchli and Martin-L¨of himself. Under the isomorphism, types correspond to propositions and members of those types, like pairs, functions and so on, to proofs. We were prepared for such a coincidence by the development of constructive logic in the last section, because the proofs we introduced there were familiar objects like pairs and functions. In the sections and chapters which follow, we shall see the extent of this correspondence, and the degree to which it can illuminate our understanding of both logic and programming. This section illustrates the core of the isomorphism by giving a reinterpretation of the rules of logic above as rules of program formation. The rules are then seen to explain

Formation rule What the types of the system are, Introduction and which expressions are members of Elimination rules which types, and

Computation rule how these objects can be reduced to simpler forms,i.e.how we canevaluate expressions. Another way of looking at the rules is to say that the formation rules explain the types of the language and that the introduction and elimination rules explain the typing rules for expressions (and so explain how type checking for the system should proceed) — together these describe thestatic

part of a traditional language, with the computation rules explaining the

dynamics of its behaviour. We shall see in section 4.10 that the distinction between the static and the dynamic becomes blurred in the full system, as type checking and computation become inextricably linked.

We now run through the rules connective by connective, changing the judgement ‘is a f ormula’ to ‘is a type’ to reflect our different orientation.

Formation Rule for∧

A is a type B is a type

4.4. THE CURRY HOWARD ISOMORPHISM 79

Introduction Rule for∧

p : A q : B

(p, q) : (A∧B)(∧I)

Elimination Rules for∧

r : (A∧B)

fst r : A (∧E1)

r : (A∧B)

snd r : B (∧E2) Computation Rules for∧

fst(p, q) → p snd(p, q) → q

Read as a type,A∧Bis the productof the two types, whose formation is permitted by the formation rule. The introduction rule tells us that members of the type include pairs (p, q) of objects, wherepis taken from the first type andq is taken from the second. The elimination rule states that from an object of the product type we can extract objects of the two component types, and the computation rule shows that the objects thus extracted are indeed the two components of the pair. These two rules therefore state that all objects of the product type are pairs.

Alternatively, we can read the elimination rules as giving the type of the two projection operators which take us from the product type to the two components. The computation rules give the computational definitions of these operators. In terms of traditional programming languages, the prod- uct type is usually called arecordtype. Nearly every modern programming language features a record type.

As we suggested above, we can think of members ofA⇒Bas functions fromAtoB. This is perhaps not surprising, as not only do we already see proofs of implications as functions, but also the arrow notation is suggestive in itself. Just to re-iterate the rules,

Formation Rule for⇒

A is a type B is a type

(A⇒B)is a type (⇒F) Introduction Rule for⇒

[x:A] .. .

e : B

This rule discharges the assumptionx:A.

This is the rule which introduces a lambda-abstraction, or function, as we explained in chapter 2. It is by a use of the lambda symbol that we form functions. We have modified the notation slightly so that the expression includes the type of the domain of the function formed. The rule which gives the type of functionapplicationsis

Elimination Rule for⇒

q : (A⇒B) a : A

(q a) : B (⇒E)

Finally, with the following rule we see our justification of the phrase ‘Computation Rule’:

Computation Rule for⇒

((λx:A). e)a → e[a/x]

This is precisely the rule of β-reduction, by which an actual parameter is substituted for the formal parameter.

Two notes on notation:

• The notation we have given for functions is complete, in that it carries the type of the hypothesis (or domain); it is unwieldy, however. In most cases we shall indicate the type by a subscript, thus:

λxA. e

and in situations where there is no danger of ambiguity, we shall simply write

λx . e

• As is traditional, we shall assume that function application is left associative and that ‘⇒’ is right associative, meaning that

f g x

abbreviates (f g)xand that

A⇒B⇒C

4.4. THE CURRY HOWARD ISOMORPHISM 81 What type operation does ∨ correspond to? Again, we should re- examine the rules for the operator:

Formation Rule for∨

A is a type B is a type

(A∨B)is a type (∨F) Introduction Rules for∨

q : A

inl q : (A∨B)(∨I1)

r : B

inr r : (A∨B)(∨I2)

Given a memberqofAwe have a corresponding member ofA∨B, namely

inl q. Similarly, ifr is inB theninr r is inA∨B. This introduction rule tells us that among the members of the typeA∨B are members of either

A or B, labelled according to their origin. As previously, the elimination rule will ensure thatonly these objects are members of the type. This kind of type is often known as adisjoint union of the two typesAandB. Such a construction appears in Pascal in the variant record construction, where a particular record type can contain different kinds of record, according to the value of a tag field. Pascal does not handle this construction very happily, and it can lead to run-time type errors. In handling a variable of variant record type the user is allowed to treat its contents as though they are of one particular variant, rather than having to deal with all the possible variants. As the particular variant that a value will have cannot be predicted at compile time, errors can result.

Is there a type-secure way of dealing with such disjoint unions? Yes, and it is given by thecasesoperator, specified in the elimination rule

Elimination Rule for∨

p : (A∨B) f : (A⇒C) g : (B⇒C)

cases p f g : C (∨E)

cases p f gis a member ofCwhich is built from a memberpofA∨B, and from functionsf : (A⇒C) andg : (B⇒C).

What is the effect of this case statement? We know that the object p

should either be a (tagged) member ofA, and have the forminl q or will be a (tagged) member of B, having the forminr r. The functionsf and

g are sufficient to give us a member ofC in either case — in the first case we get a member ofC by applyingf toq, and in the second by applyingg

tor. This computational information is expressed by:

Computation Rules for∨

cases(inr r)f g → g r

The last rules we gave were for the type⊥, the absurd proposition. We characterised this as a formula without proofs, so under our other view, it is atype without members, theempty type.

Formation Rule for⊥ ⊥is a type(⊥F) Elimination Rule for⊥

p : ⊥

abortAp : A

(⊥E)

This rule says that if we can find a member pof the empty type then our program should abort — we express this by saying that for any A at all, the objectabortApis a member ofA.

The final rule we saw was the rule of assumption; in order for the as- sumption thatxis a member ofA to make sense,A must be a type.

Rule of Assumption A is a type

x:A (AS)

As we said earlier, in many of our examples we shall omit the derivation of ‘A is a type’, assuming it has already been performed. Nonetheless, the system does not make sense without this condition.

That completes our second reading of the rules, and shows that they can equally well be read as

• rules for the types and objects of a typed functional programming system and as

• rules for the propositions and proofs of a logic.

We shall explore the correspondence further in the coming sections, seeing some of the ramifications of the correspondence in propositional logic, and also how extensions to both the logic and the functional language have their analogues. Finally we will explore the consequences of this correspondence for programming methodology. Note also that we have not yet introduced any dependent types — we do this with the identity orI types of section 4.10.