Principles of Programming Languages Lecture Notes - Computer

37
BU CAS CS 520 Principles of Programming Languages Lecture Notes Hongwei Xi Computer Science Department, Boston University 111 Cummington Street, Boston, MA 02215

Transcript of Principles of Programming Languages Lecture Notes - Computer

BU CAS CS 520

Principles of Programming Languages

Lecture Notes

Hongwei XiComputer Science Department, Boston University

111 Cummington Street, Boston, MA 02215

2

Chapter 1

Simply-Typed Lambda-Calculus

1.1 Syntax

constants c ::= true | false | 0 | 1 | −1 | · · ·operators op ::= + | − | ∗ | / | · · ·terms t ::= c | x | if t0 then t1 else t2 | op(t) | λx : T.t | t1(t2)values v ::= c | λx : T.ttypes T ::= Bool | Int | T1 → T2

contexts Γ ::= ∅ | Γ, x : T

1.2 Static Semantics

c ∈ true, falseΓ ` c : Bool

(T-Bool)

c ∈ 0, 1,−1, . . .Γ ` c : Int

(T-Int)

Γ ` t0 : Bool Γ ` t1 : T Γ ` t2 : TΓ ` if t0 then t1 else t2 : T

(T-If)

Σ(op) = T1 → T2 Γ ` t : T1

Γ ` op(t) : T2(T-Op)

Γ(x) = T

Γ ` x : T(T-Var)

Γ, x : T1 ` t : T2

Γ ` λx : T1.t : T1 → T2(T-Abs)

Γ ` t1 : T1 → T2 Γ ` t2 : T1

Γ ` t1(t2) : T2(T-App)

3

4 CHAPTER 1. SIMPLY-TYPED LAMBDA-CALCULUS

1.3 Dynamic Semantics

t0 → t′0if t0 then t1 else t2 → if t′0 then t1 else t2

(E-If)

if true then t1 else t2 → t1(E-IfTrue)

if false then t1 else t2 → t2(E-IfFalse)

t→ t′

op(t)→ op(t′)(E-Op)

op(v) = v′

op(v)→ v′(E-OpVal)

t1 → t′1t1(t2)→ t′1(t2)

(E-App1)

t2 → t′2v1(t2)→ v1(t′2)

(E-App2)

(λx.t1)(v2) ` [x 7→ v2]t1(E-AppAbs)

1.4 Properties of Typing

Lemma 1 (Inversion) Given a typing derivation D :: Γ ` t : T , the last applied typing rule in D isuniquely determined by the syntactic structure of t.

Lemma 2 (Canonical Forms)

1. If v is a closed value of the type Bool, then v is either true or false.

2. If v is a closed value of the type Int, then v ∈ 0, 1,−1, . . . holds.

3. If v is a closed value of the type T1 → T2, then v is of the form λx : T1.t.

Theorem 3 (Progress) Suppose that t is a closed and well-typed terms, that is, there exists a deriva-tion D :: ∅ ` t : T . Then either t is a value or t→ t′ holds for some term t′.

Proof We proceed by structural induction on D. Clearly, we only need to handle the cases wheret is not a value.

• D is of the following form,

D0 :: Γ ` t0 : Bool Γ ` t1 : T Γ ` t2 : TΓ ` if t0 then t1 else t2 : T

(T-If)

where t = if t0 then t1 else t2.

– t0 is a value. Then t0 is either true or false by Lemma 2. Hence, t → t1 or t → t2according to t being true or false.

1.4. PROPERTIES OF TYPING 5

– t0 is not a value. By induction hypothesis on D0, t0 → t′0 for some t′0. Hence, t →if t′0 then t1 else t2.

• D is of the following form,

Σ(op) = T1 → T2 Γ ` t1 : T1

D1 :: Γ ` op(t1) : T2(T-Op)

where t = op(t1) and T = T2.

– t1 is not a value. Then t1 → t′1 by induction hypothesis on D1. Hence, t→ op(t′1).

– t1 is a value. Then t→ v, where v is the value of op(t1).

• D is of the following form,

D1 :: Γ ` t1 : T1 → T2 D2 :: Γ ` t2 : T1

Γ ` t1(t2) : T2(T-App)

where t = t1(t2) and T = T1.

– t1 is not a value. Then by induction hypothesis on D1, t1 → t′1 for some t′1. Hence,t→ t′1(t2).

– t1 is a value. Then by induction hypothesis on D2, t2 → t′2 for some t′2. Hence, t→ t1(t′2).

– t1 and t2 are values. Then by Lemma 2, t1 is of the form λx : T.t′1. Hence, t→ [x 7→ t2]t′1.

Lemma 4 (Substitution) If Γ, x : S ` t : T and Γ ` s : S, then Γ ` [x 7→ s]t : T .

Theorem 5 (Subject Reduction) If D :: Γ ` t : T and t→ t′, then Γ ` t′ : T is derivable.

Proof We proceed by structural induction on D. Note that t is not a value since t→ t′ holds.

• D is of the following form,

D0 :: Γ ` t0 : Bool D1 :: Γ ` t1 : T D2 :: Γ ` t2 : TΓ ` if t0 then t1 else t2 : T

(T-If)

where t = if t0 then t1 else t2.

– t0 → t′0 and t → t′ = if t′0 then t1 else t2. By induction hypothesis on D0, we havederivation D′0 :: Γ ` t′0 : Bool . Therefore, Γ ` t′ : T can be derived as follows.

D′0 :: Γ ` t′0 : Bool D1 :: Γ ` t1 : T D2 :: Γ ` t2 : TΓ ` if t′0 then t1 else t2 : T

(T-If)

– t0 = true and t→ t′ = t1. Note D1 :: Γ ` t1 : T and we are done.

– t0 = false and t→ t′ = t2. Note D2 :: Γ ` t2 : T and we are done.

6 CHAPTER 1. SIMPLY-TYPED LAMBDA-CALCULUS

• D is of the following form,

Σ(op) = T1 → T2 Γ ` t1 : T1

D1 :: Γ ` op(t1) : T2(T-Op)

where t = op(t1) and T = T2.

– t1 → t′1 and t → t′ = op(t′1). By induction hypothesis on D1, we have D′1 :: Γ ` t′1 : T1.Hence, Γ ` t′ : T can be derived as follows.

Σ(op) = T1 → T2 Γ ` t1 : T1

D′1 :: Γ ` op(t1) : T2(T-Op)

– t1 is a value and t → t′ = v for the value v of op(t1). Given the type of op, v must havethe type T2. Hence, Γ ` t′ : T is derivable.

• D is of the following form,

D1 :: Γ ` t1 : T1 → T2 D2 :: Γ ` t2 : T1

Γ ` t1(t2) : T2(T-App)

where t = t1(t2) and T = T1.

– t1 → t′1 and t→ t′ = t′1(t2). By induction hypothesis onD1, we haveD′1 :: Γ ` t′1 : T1 → T2.Hence, Γ ` t′ : T can be derived as follows.

D′1 :: Γ ` t′1 : T1 → T2 D2 :: Γ ` t2 : T1

Γ ` t1(t2) : T2(T-App)

– t1 is a value and t2 → t′2 and t → t′ = t1(t′2). By induction hypothesis on D2, we haveD′2 :: Γ ` t′2 : T2. Hence, Γ ` t′ : T can be derived as follows.

D1 :: Γ ` t1 : T1 → T2 D′2 :: Γ ` t′2 : T1

Γ ` t1(t2) : T2(T-App)

– t1 = λx : T1.t′1 for some t′1 and t2 is a value and t → t′ = [x 7→ t2]t′1. Then D1 is of the

following formΓ, x : T1 ` t′1 : T2

Γ ` λx : T1.t′1 : T1 → T2

(T-Abs)

By the Substitution Lemma, Γ ` [x 7→ t2]t′1 : T2 is derivable. Note that t′ = [x 7→ t2]t′1and we are done.

1.5 Evaluation Contexts

evaluation contexts E ::= [] | if E then t1 else t2 | op(E) | E(t) | v(E)

Definition 6 A redex is a special form of term.

1.6. TYPE ERASUE AND TYPABILITY 7

• if true then t1 else t2 is a redex and its reduction is t1.

• if false then t1 else t2 is a redex and its reduction is t2.

• op(v1) is a redex if op(v1) = v2 and its reduction is v2.

• (λx : T.t)(v) is a redex and its reduction is [x 7→ v]t.

Assume that t1 = E[t] and t2 = E[t′], where t is a redex and t′ is its reduction. Then we write t1 → t2and say that t1 reduces to t2 in one step. Let →∗ be the reflexive and transitive closure of →.

Proposition 7 Assume E[t] = E′[t′], where t and t′ are redexes. Then E = E′ and t = t′.

Proof By structural induction on E.

Theorem 8 (Subject Reduction) Assume D :: ∅ ` t : T and t→ t′. Then ∅ ` t′ : T is derivable.

Proof Assume that t = E[t1] and t′ = E[t′1], where t1 is a redex and t′1 is the reduction of t1. Theproof proceeds by structural induction on E.

Lemma 9 Assume D :: ∅ ` t : T . Then t is a value or t = E[t0] for some evaluation context E andredex t0.

Proof By structural induction on D.

Theorem 10 (Progress) Assume D :: ∅ ` t : T . Then t is a value or t→ t′ for some term t′.

Proof Assume that t is not a value. By Lemma 9, t = E[t0] for some evaluation context E andredex t0. Hence, we have t→ t′ for t′ = E[t′0], where t′0 is the reduction of the redex t0.

1.6 Type Erasue and Typability

8 CHAPTER 1. SIMPLY-TYPED LAMBDA-CALCULUS

Chapter 2

Simple Extensions

2.1 Base Types

2.2 The Unit Type

2.3 Derived Forms: Sequencing and Wildcards

terms t ::= . . . | t1; t2 | λ : Unit.t

t1 → t′1t1; t2 → t′1; t2

(E-Seq)

unit; t2 → t2(E-SeqNext)

2.4 Ascription

terms t ::= . . . | t as T

t→ t′

t as T → t′ as T(E-Ascribe)

v as T → v(E-AscribeVal)

2.5 Let Bindings

terms t ::= . . . | let x = t1 in t2

t1 → t′1let x = t1 in t2 → let x = t′1 in t2

(E-Let)

let x = v1 in t2 → [x 7→ v1]t2(E-LetVal)

9

10 CHAPTER 2. SIMPLE EXTENSIONS

2.6 Pairs

types T ::= . . . | T1 ∗ T2

terms t ::= . . . | t1, t2 | t.1 | t.2values v ::= . . . | v1, v2

Γ ` t1 : T1 Γ ` t2 : T2

Γ ` t1, t2 : T1 ∗ T2(T-Pair)

Γ ` t : T1 ∗ T2

Γ ` t.1 : T1(T-Proj1)

Γ ` t : T1 ∗ T2

Γ ` t.1 : T2(T-Proj2)

t1 → t′1t1, t2 → t′1, t2

(E-Pair1)

t2 → t′2v1, t2 → v1, t

′2

(E-Pair2)

t→ t′

t.1→ t′.1(E-Proj1)

v1, v2.1→ v1(E-Proj1Val)

t→ t′

t.2→ t′.2(E-Proj2)

v1, v2.2→ v2(E-Proj2Val)

2.7 Tuples

2.8 Records

types T ::= . . . | l1 : T1, . . . , ln : Tnterms t ::= . . . | l1 = t1, . . . , ln = tn | t.l

Γti : Ti for i = 1, . . . nΓ ` l1 = t1, . . . , ln = tn : l1 : T1, . . . , ln : Tn

T-Record

2.9 Sums

terms t ::= . . . | inl(t) | inr(t) | case t of inl(x)⇒ t1 | inr(x)⇒ t2

2.10. VARIANTS 11

Γ ` inl(t1) : T1 + T2

Γ ` t1 : T1(T-Inl)

Γ ` inr(t2) : T1 + T2

Γ ` t2 : T2(T-Inr)

Γ ` t : T1 + T2 Γ, x : T1 ` t1 : T Γ, x : T2 ` t2 : TΓ ` case t of inl(x)⇒ t1 | inr(x)⇒ t2 : T

(T-Case)

case inl(v) of inl(x)⇒ t1 | inr(x)⇒ t2 → [x 7→ v]t1(E-CaseInl)

case inr(v) of inl(x)⇒ t1 | inr(x)⇒ t2 → [x 7→ v]t2(E-CaseInr)

t→ t′

case t of inl(x)⇒ t1 | inr(x)⇒ t2 → case t′ of inl(x)⇒ t1 | inr(x)⇒ t2(E-Case)

2.10 Variants

2.11 General Recursion

terms t ::= . . . | fix(t) | letrec x : T1 = t1 in t2

Γ ` t : T → TΓ ` fix(t) : T

(T-Fix)

t→ t′

fix(t)→ fix(t′)(E-Fix)

fix(λx : T.t)→ [x 7→ fix(λx : T.t)]t(E-FixVal)

12 CHAPTER 2. SIMPLE EXTENSIONS

Chapter 3

Normalization

Definition 11 Given a term t, let l(t) be the least upper bound on the numbers of reduction stepsin reduction sequences starting from t.

By the Konig’s lemma, l(t) = ∞ if and only if there is an infinite reduction sequence starting fromt. We write t ↓ to mean l(t) <∞.

Definition 12 (Reducibility) For each type T , we define a predicate RT on closed terms of type T .

• T is a base type. Then RT (t) holds if t ↓.

• T = T1 ∗ T2. Then RT (t) holds if t ↓ and RT1(v1) and RT2(v) hold whenever t→∗ v1, v2.

• T = T1 → T2. Then RT (t) holds if t ↓ and RT2([x 7→ v1]t2) holds whenever t→∗ λx : T1.t2 andRT1(v1).

Proposition 13 Assume that t is a closed expression of type T .

1. If RT (t), then t ↓.

2. If RT (t) and t→ t′, then RT (t′).

3. If t is not a value and RT (t′) for every t′ satisfying t→ t′, then RT (t).

Proof (1) and (2) are straightforward. We now prove (3) by structural induction on T .

• T is a base type. Then l(t) ≤ max(0 ∪ 1 + l(t′) | t → t′). Therefore, t ↓, which impliesRT (t).

• T = T1 ∗ T2 for some types T1 and T2. Assume that t →∗ v1, v2 for some values v1 and v2.Since t is not a value, there exists a term t′ of type T such that t→ t′ →∗ v1, v2 holds. SinceRT (t′), RTi(vi) for i = 1, 2. Hence, RT (t) by the definition of RT .

• T = T1 → T2 for some types T1 and T2. Assume that t →∗ λx : T1.t2. Since t is not avalue, there exists a term t′ of type T such that t → t′ and t′ →∗ λx : T1.t2. Since RT (t′),RT2([x 7→ v1]t2) for every v1 satisfying RT1(v1). Hence, RT (t) by the definition of RT .

Therefore, (3) is valid.

13

14 CHAPTER 3. NORMALIZATION

Lemma 14 (Main lemma) Assume that Γ ` t : T is derivable and ` θ : Γ holds. If RΓ(x)(θ(x)) forall x ∈ dom(θ) = dom(Γ), then RT (t[θ]).

Proof By structural induction on a derivation D of Γ ` t : T .

• D is of the following form,

D0 :: Γ ` t0 : Bool D1 :: Γ ` t1 : T D2Γ ` t2 : TΓ ` if t0 then t1 else t2 : T

(T-If)

where t = if t0 then t1 else t2. By induction hypothesis on D0, RBool (t0[θ]) holds. Also,RT (t1[θ]) and RT (t2[θ]) hold by induction hypothese on D1 and D2, respectively.

We now prove by induction on l(t0) that ifRBool (t0),RT (t1) andRT (t2), thenRT (if t0 then t1 else t2).Assume that t = RT (if t0 then t1 else t2)→ t′.

– t0 → t′0 and t→ t′ = if t′0 then t1 else t2. Then l(t′0) < l(t0) and by induction hypothesison t′0, RT (t′) holds.

– t0 = true and t→ t′ = t1. Then obviously RT (t′) holds.

– t0 = false and t→ t′ = t2. Then obviously RT (t′) holds.

Hence by Proposition 13 (3), RT (t) holds.

We can now conclude that RT (t[θ]) holds as t[θ] = if t0[θ] then t1[θ] else t2[θ].

• D is of the following form,

D1 :: Γ ` t1 : T1 → T2 D2 :: Γ ` t2 : T1

Γ ` t1(t2) : T2(T-App)

where t = t1(t2) and T = T2. Assume θ : Γ. By induction hypothesis on D1 and D2, bothRT1→T2(t1[θ]) and RT2(t2[θ]) hold.

We now prove by induction on l(t1) + l(t2) that for all terms t1 and t2, RT1→T2(t1) and RT2(t2)implies RT2(t1(t2)). Assume that t→ t′. There are three possibilities.

– t1 → t′1 and t′ = t′1(t2). Since l(t′1) + l(t2) < l(t1) + l(t2), RT2(t′) holds by inductionhypothesis.

– t1 = v1 for some value v1, t2 → t′2 and t′ = t1(t′2). Since l(t1) + l(t′2) < l(t1) + l(t2), RT2(t′)holds by induction hypothesis.

– t1 = λx : T1.t11 for some term t11, t2 = v2 for some value v2 and t′ = [x 7→ v2]t11. SinceRT1→T2(t1) and RT2(t2), RT2(t′) by the definition of RT1→T2 .

Therefore, RT (t) by Proposition 13 (3).

We can now conclude that RT2(t[θ]) holds as t[θ] = t1[θ](t2[θ]).

• D is of the following form,

Γ, x : T1 ` t2 : T2

D1 :: Γ ` λx : T1.t2 : T1 → T2(T-Abs)

15

where t = λx : T1.t2 and T = T1 → T2.

Assume θ : Γ. Let t∗ = t[θ] = λx : T1.t2[θ] and we need to show RT (t∗). Assume RT1(v1) forsome value v1. Then [x 7→ v1]t2[θ] = t2[θ[x 7→ v1]]. Note that θ[x 7→ v1] : Γ, x : T1 holds. Byinduction hypothesis on D1, RT2(t2[θ[x 7→ v1]]) holds. Therefore, RT (t∗) by the definition ofRT .

The rest of cases are trivial.

Theorem 15 If t is a well-typed closed term, then t ↓.

Proof By Lemma 14, RT (t). Therefore, t ↓ by Proposition 13 (1).

16 CHAPTER 3. NORMALIZATION

Chapter 4

References

4.1 Introduction

terms t ::= . . . | ref(t) | !t | t1 := t2 | lvalues v ::= . . . | ltypes T ::= . . . | Ref(T )

Note that we use l for a reference, which is a value.

Here is an example where recursion is achieved through reference.

val fact: (int -> int) ref = ref (fn n => 0)

val _ = fact := (fn (n: int): int => if n = 0 then 1 else n * !fact (n-1))

4.2 Typing

Γ ` t : TΓ ` ref(t) : Ref(T )

(T-Ref)

Γ ` t : Ref(T )Γ `!t : T

(T-DeRef)

Γ ` t1 : Ref(T ) Γ ` t2 : TΓ ` t1 := t2 : Unit

(T-Assign)

17

18 CHAPTER 4. REFERENCES

4.3 Evaluation

The existing evaluation rules can be augmented with a store straightforwardly. For instance, we nowhave the following evaluation rules.

t1 | µ→ t′1 | µ′

t1(t2) | µ→ t′1(t2) | µ′(E-App1)

t2 | µ→ t′2 | µ′

v1(t2) | µ→ v1(t′2) | µ′(E-App2)

(λx.t1)(v2) | µ ` [x 7→ v2]t1 | µ(E-AppAbs)

Here are the new evaluation rules.

t | µ→ t′ | µ′

ref(t) | µ→ ref(t′) | µ′(E-Ref)

l 6∈ dom(µ)ref(v) | µ→ l | (µ, l 7→ v)

(E-RefVal)

!t | µ→!t′ | µ′

t | µ→ t′ | µ′(E-DeRef)

l ∈ dom(µ)!l | µ→ µ(l) | µ (E-DeRefVal)

l ∈ dom(µ)l := v | µ→ unit | µ[l := v]

(E-AssignVal)

4.4 Store Typings

Σ(l) = T

Γ | Σ ` l : Ref(T )(T-Loc)

Γ | Σ ` t : TΓ | Σ ` ref(t) : Ref(T )

(T-Ref)

Γ | Σ `!t : TΓ | Σ ` t : Ref(T )

(T-DeRef)

Γ | Σ ` t1 : Ref(T ) Γ ` t2 : TΓ | Σ ` t1 := t2 : Unit

(T-Assign)

4.5 Safety

Definition 16 A store µ is said to be well-typed with respect to a typing context Γ and a store typingΣ, written Γ | Σ ` µ if dom(µ) = dom(Σ) and Γ | Σ ` µ(l) : Σ(l) for every l ∈ dom(µ) = dom(Σ).

Theorem 17 (Type Preservation) If Γ | Σ ` t : T , Γ | Σ ` µ and t | µ → t′ | µ′, then for someΣ′ ⊇ Σ, Γ | Σ′ ` t′ : T ′ and Γ | Σ′ ` µ′.

4.5. SAFETY 19

Theorem 18 (Progress) Suppose D :: ∅ | Σ ` t : T . Then either t is a value or for any store µ suchthat ∅ | Σ ` µ, t | µ→ t′ | µ′ holds for some t′ and µ′.

20 CHAPTER 4. REFERENCES

Chapter 5

Exceptions

Exceptions provide a means to altering the normal control in the execution of a program. Forinstance, the following example indicates a way to terminate the execution of a loop by executingthe break command.

while (test) ...if (something_is_true) break;...

This can be readily implemented through the use of exceptions. A raised exception may be capturedlater so as to be handled by an exception handler.

datatype binaryTree = E | B of binaryTree * binaryTree

fun isBraunTree (t: binaryTree): bool =let

exception NotBraunTree

fun aux (E) = 0| aux (B (t1, t2)) =

letval ls = aux t1 and rs = aux t2

inif ls = rs orelse ls = rs + 1 then 1 + ls + rselse raise NotBraunTree

endin

letval _ = aux t

intrue

end handle NotBraunTree => falseend

21

22 CHAPTER 5. EXCEPTIONS

5.1 Raising and Handling Exceptions

constants c ::= . . . | errorterms t ::= . . . | raise(t) | try t1 with t2answers ans ::= v | raise(v)

Γ ` t : ExnΓ ` raise(t) : T

(T-Raise)

Γ ` t1 : T Γ ` t2 : Exn → TΓ ` try t1 with t2 : T

(T-TryWith)

t→ t′

raise(t)→ raise(t′)(E-Raise)

raise(v)(t2)→ raise(v)(E-Raise-App1)

v1(raise(v))→ raise(v)(E-Raise-App2)

t1 → t′1try t1 with t2 → try t′1 with t2

(E-TryWith)

try v1 with t2 → v1(E-TryWithVal)

try raise(v) with t2 → t2(v)(E-TryWithExn)

Theorem 19 (Subject Reduction) Assume that D :: Γ ` t : T and t → t′. Then Γ ` t′ : T isderivable.

Theorem 20 (Progress) Assume that D :: ∅ ` t : T . Then either t is an answer or t→ t′ for someterm t′.

Chapter 6

Recursive Types

6.1 Examples

IntList = 〈nil : Unit , cons : Int ∗ IntList〉

IntList = µX.〈nil : Unit , cons : Int ∗X〉

nil = 〈nil = unit〉cons = λx : Int .λxs : tIntList.〈cons = x, xs〉isNil = λxs.case xs of 〈nil = u〉 ⇒ true | 〈cons = p〉 ⇒ falsehd = λxs.case xs of 〈nil = u〉 ⇒ raise(EmptyList) | 〈cons = p〉 ⇒ p.1tl = λxs.case xs of 〈nil = u〉 ⇒ raise(EmptyList) | 〈cons = p〉 ⇒ p.2

T1 = µX.Int → XT2 = µX.X → Int

f1 = fix(λf : Int → T1.λn : Int .f)Ω = (λx : T2.x(x))(λx : T2.x(x))

Stream = µX.Unit → Int ∗XProcess = µX.Int → Int ∗X

upFrom = fix(λf : Int → Stream.λn : Int .λ : Unit.n ∗ f(n+ 1))Nats = upFrom(0)

In the presence of recursive types, we can construct a nonterminating function without using thefixed point operator fix.

datatype T = C of T -> Tfun f (x: T): T = case x of C g => g (x)

Note that the evaluation of f(C(f)) is nonterminating.Here is a representation of untyped λ-terms through the use of higher-order abstract syntax.

23

24 CHAPTER 6. RECURSIVE TYPES

datatype T = Lam of T -> T | App of T * T

|x| = x|λx.t| = Lam(λx : T.|t|)|t1(t2)| = App(|t1|, |t2|)

6.2 Formalization

types T ::= . . . | X | µX.T

fold([X 7→ µX.T ]T ) = µX.Tunfold(µX.T ) = [X 7→ µX.T ]T

U = µX.T Γ ` t : [X 7→ U ]TΓ ` t : U

(T-Fold)

U = µX.T Γ ` t : UΓ ` t : [X 7→ U ]T

(T-Unfold)

Chapter 7

Universal Types

7.1 System F

types T ::= X | T → T | ∀X.Tterms t ::= x | λx : T.t | t1(t2) | ΛX.t | t[T ]values v ::= λx : T.t | ΛX.tcontexts Γ ::= ∅ | Γ, x : T

Encoding Datatypes

Pairs Let us define Pair(T1, T2) as ∀X.(T1 → T2 → X)→ X.

pair(x, y) = ΛX.λp : T1 → T2 → X.p(x)(y)fst(p) = p[T1](λx : T1λy : T2.x)snd(p) = p[T2](λx : T1λy : T2.y)

Natural Numbers Let us define Nat as ∀X.X → (X → X) → X. Then the two constructors Zand S can be defined as follows.

Z = ΛX.λz : X.λs : X → X.zS(n : Nat) = ΛX.λz : X.λs : X → X.s(n[X](z)(s))

Lists Let us define List(T ) as ∀X.X → (T → X → X) → X. Then the two list constructors Niland Cons can be defined as follows.

Nil = ΛX.λnil : X.λcons : T → X → X.nilCons(x : T )(xs : List(T )) = ΛX.λnil : X.λcons : T → X → X.cons(x)(xs[X](nil)(cons))

7.2 Some Basic Properties

Definition 21 Given a type variable X, a type T and a context Γ, we write [X 7→ T ]Γ for thecontext Γ′ such that dom(Γ) = dom(Γ′) and Γ′(x) = [X 7→ T ](Γ(x)).

Lemma 22 Assume D :: ~X; Γ ` t : T and ~X ` T1 [type]. Then ~X; [X 7→ T1]Γ ` [X 7→ T1]t : [X 7→T1]T is derivable.

25

26 CHAPTER 7. UNIVERSAL TYPES

~X ` ∅ [ctx]

~X ` Γ [ctx] ~X ` T [ctx]~X ` Γ, x : T [ctx]

X is in ~X~X ` X [type]

(K-Var)

~X ` T1 [type] ~X ` T2 [type]~X ` T1 → T2 [type]

(K-Fun)

~X,X ` T [type]~X ` ∀X.T [type]

(K-Uni)

~X ` Γ [ctx] Γ(x) = T

~X; Γ ` x : T(T-Var)

~X; Γ, x : T1 ` t : T2

~X; Γ ` λx : T1.t : T1 → T2

(T-Abs)

~X; Γ ` t1 : T1 → t2 ~X,Γ ` t2 : T1

~X; Γ ` t1(t2) : T2

(T-App)

~X,X; Γ ` t : T ~X ` Γ [ctx]~X; Γ ` ΛX.t : ∀X.T

(T-Tabs)

~X; Γ ` t : ∀X.T ~X ` T0 [type]~X; Γ ` t[T0] : [X 7→ T0]T

(T-Tapp)

t1 → t′1t1(t2)→ t′1(t2)

(E-App1)

t2 → t′2v1(t2)→ v1(t′2)

(E-App2)

t1 → t′1t1(t2)→ t′1(t2)

(E-App2)

(λx : T1.t1)(v2)→ [x 7→ v2]t1(E-AppAbs)

t[T ]→ t′[T ]t→ t′

(E-Tapp)

(ΛX.t)[T ]→ [X 7→ T ]t(E-TappTabs)

7.3. TYPE ERASURE 27

Proof The proof follows from structural induction on D.

Theorem 23 (Subject Reduction) Assume that D :: ~X; Γ ` t : T and t → t′. Then ~X; Γ ` t′ : T isderivable.

Proof We proceed by structural induction on D.

• D has the following form,

D1 :: ~X; Γ ` t1 : ∀X.T1~X ` T2 [type]

~X; Γ ` t1[T2] : [X 7→ T2]T1

(T-Tapp)

where t = t1[T2] and T = [X 7→ T2]T1. We now have two subcases.

– t1 → t′1 and t→ t′ = t′1[T2]. By induction hypothesis on D1, we have D′1 :: Γ ` t′1 : ∀X.T1

for some D′1, and therefore ~X; Γ ` t′ : T is derivable.

– t1 = ΛX.t′1 and t→ t′ = [X 7→ T2]t′1. Then D1 has the following form:

~X,X; Γ ` t1 : T1~X ` Γ [ctx]

~X; Γ ` ΛX.t′1 : ∀X.T1

(T-Tabs)

where t = ΛX.t1 and T = ∀X.T1. By Lemma 22, ~X; Γ ` [X 7→ T2]t′1 : [X 7→ T2]T1

is derivable since Γ contains no free occurrences of X. Note that t′ = [X 7→ T2]t′1 andT = [X 7→ T2]T1, and we are done.

The other cases can be handled similarly.

Theorem 24 (Progress) Assume D :: ~X; Γ ` t : T . Then t is a value or t→ t′ holds for some termt′.

Proof The proof follows from structural induction on D.

7.3 Type Erasure

We can define a type erasure function | · | as follows, which translates a term in System F into anuntyped λ-term.

|x| = x |λx : T.t| = λx.|t| |t1(t2)| = |t1|(|t2|) |ΛX.t| = |t| |t[T ]| = |t|

Notice that for a value v in System F, |v| may not necessarily be a value. Therefore, given a termt in System F, |t| →∗ v0 does not necessarily imply that we have t →∗ v for some value v such that|v| = v0. To have this property, we can impose a restriction on (T-Tabs) by requiring that t be avalue whenever the following rule is applied.

~X,X; Γ ` t : T ~X ` Γ [ctx]~X; Γ ` ΛX.t : ∀X.T

(T-Tabs)

This restriction is often called value restriction.

28 CHAPTER 7. UNIVERSAL TYPES

7.4 Normalization for System F

Definition 25 Given a closed type T , a predicate R defined on the closed terms of the type T is areducibility candidate of type T if R satisfies the following conditions.

• If R(t) then t ↓.

• If R(t) and t→ t′ then R(t′).

• If t is not a value and R(t′) whenever t→ t′, then R(t).

For instance, the predicate R(t) ≡ t ↓ defined on the closed terms of a given type T is a reducibilitycandiate of the type T .

We use Θtyp for a substitution that maps type variables to types and Θred for a finite map thatmaps type variables to reducibility candidates. We write Θred : Θtyp if for each X ∈ dom(Θred) =dom(Θtyp), Θred(X) is a reducibility candidate of type Θ∗(X). In addition, we write Θtyp : ~X ifdom(Θtyp) = ~X.

Definition 26 Assume that ~X ` T [type] is derivable and Θred : Θtyp : ~X. We define Red [Θred; Θtyp;T ]as follows by structural induction on T .

• T is a type variable. Then Red [Θred; Θtyp;T ] = Θred(T ).

• T = T1 → T2. Then Red [Θred; Θtyp;T ](t) if t ↓ and whenever t →∗ λx : T1[Θtyp].t2, we haveRed [Θred; Θtyp;T2]([x 7→ v1]t2) for each v1 satisfying Red [(]Θred; Θtyp;T1)(v1).

• T = ∀X.T1. Then Red [Θred; Θtyp;T ](t) if t ↓ and whenever t →∗ ΛX.t1, Red [Θred[X 7→R]; Θtyp[X 7→ T2];T1]([X 7→ T2]t1) holds for each reducibility candidate R of T2.

Proposition 27 Red [Θred; Θtyp;T ] is a reducibility candidate of the type T [Θtyp].

Proof The proof immedidately follows from structural induction on T .

Proposition 28 We have the following:

Red [Θred; Θtyp; [X 7→ T1]T ] = Red [Θred[X 7→ Red [Θred; Θtyp;T1]]; Θtyp[X 7→ T1[Θtyp]];T ]

Proof The proof immediately follows from structural induction on T .

Lemma 29 Assume D :: ~X; Γ ` t : T and Θred : Θtyp : ~X. Also, assume θ : Γ[Θtyp] andRed [Θred; Θtyp; Γ(x)](θ(x)) for each x ∈ dom(θ). Then Red [Θred; Θtyp;T ](t[Θtyp][θ]) holds.

Proof We proceed by structural induction on D.

Theorem 30 (Normalization) Assume that ∅; ∅ ` t : T is derivable. Then t ↓ holds.

Proof By Lemma 29, Red [[]; [];T ](t) holds. Since Red [[]; [];T ] is a reducibility candidate by Propo-sition 27, t ↓ holds.

Chapter 8

Existential Types

8.1 Introduction

types T ::= . . . | ∃X.Tterm t ::= . . . | ∗T1, t as T2 | open t1 as ∗X,x in t2values v ::= . . . | ∗T1, v as T2

~X ` S [type] ~X; Γ ` t : [X 7→ S]T~X; Γ ` ∗S, t as ∃X.T : ∃X.T

(T-Pack)

~X; Γ ` t1 : ∃X.T1~X,X; Γ, x : T1 ` t2 : T2

~X ` T2 [type]~X; Γ ` open t1 as ∗X,x in t2 : T2

(T-Unpack)

t→ t′

∗T1, t as T2 → ∗T1, t′ as T2

(E-Pack)

t1 → t′1open t1 as ∗X,x in t2 → open t′1 as ∗X,x in t2

(E-Unpack)

open (∗T1, v as T2) as ∗X,x in t2 → [x 7→ v][X 7→ T1]t2(E-UnpackVal)

8.2 Data Abstraction with Existentials

Pair[T1][T2] : ∃X.pair : T1 → T2 → X, fst : X → T1, snd : X → T2Sum[T1][T2] : ∃X.inl : T1 → X, inr : T2 → X, caseof : ∀Y.X → (T1 → Y )→ (T2 → Y )→ Y

8.3 Encoding Existentials

∃X.T = ∀Y.(∀X.T → Y )→ Y∗S, t as ∃X.T = let x = t in ΛY.λf : ∀X.T → Y.f [S](x)

open t1 as ∗X,x in t2 = t1[T2](ΛX.λx : T1.t2)

29

30 CHAPTER 8. EXISTENTIAL TYPES

*(T_1 * T_2),pair = \x:T_1.\y:T_2.x, yfst = \p:T_1 * T_2. p.1snd = \p:T_1 * T_2. p.2

*(T_2 * T_1),pair = \x:T_1.\y:T_2.y, xfst = \p:T_1 * T_2. p.2snd = \p:T_1 * T_2. p.1

*(forall X.(T_1 -> T_2 -> X) -> X),pair = \x:T_1.\y:T_2.\X.\p:T_1 -> T_2 -> X. p(x)(y),fst = \p:forall X.(T_1 -> T_2 -> X) -> X.p[T_1](\x:T_1.\y:T_2.x),snd = \p:forall X.(T_1 -> T_2 -> X) -> X.p[T_1](\x:T_1.\y:T_2.y)

*(forall X.(T_1 -> X) -> (T_2 -> X) -> X),inl = \x:T_1.\X.\l:T_1 -> X.\r:T_2 -> X.l(x),inr = \x:T_1.\X.\l:T_1 -> X.\r:T_2 -> X.r(x),caseof =

\Y.\s:forall X.(T_1 -> X) -> (T_2 -> X) -> X.\lc:T_1 -> Y.\rc:T_2 -> Y. s[Y](lc)(rc)

8.3. ENCODING EXISTENTIALS 31

signature STACK =sig

type T

val new: unit -> Tval isEmpty: T -> boolval length: T -> intval pop: T -> int * Tval push: int * T -> T

end

structure Stack: STACK =struct

type T = int list

fun new () = []

val isEmpty = List.isEmptyval length = List.length

fun pop (s: T): int * T =case s of [] => raise EmptyStack | x :: xs => (x, xs)

fun push (e: int, s: T): T = e :: s

end

32 CHAPTER 8. EXISTENTIAL TYPES

Chapter 9

Type Reconstruction

It can be burdensome for the programmer to write types when programming. Therefore, there is animmediate question as to whether we can find a satisfactory approach that allows the programmerto omit writing types and then infers the omitted types from the structure of a program. We presenta positive answer to this question in this section.

9.1 External Language

We present an external language for TFPL0. In this language, the programmer is allowed to omitwriting types when defining a function fun f(x) is e. On the other hand, the programmer is alsoallowed to write (e : τ) to indicate that the expression e must have type τ .

expressions e ::= x | f | b | i | op(e1, . . . , en) | if e then e1 else e2 | | e1, e2 | e.1 | e.2 |fun f(x) is e | fun f(x : τ1) : τ2 is e |app(e1, e2) | let x = e1 in e2 | (e : τ)

Note that we define the type erasure of (e : τ) as |e|, that is, |(e : τ)| = |e|.

9.2 Type Reconstruction Algorithm

We need the following syntax for presenting a type inference algorithm for TFPL0.

Existential Type Variables XTypes T ::= X | bool | int | 1 | T ∗ T | T → TContexts G ::= · | G, x : TType Constraints Φ ::= > | T1

.= T2 | Φ1 ∧ Φ2

Substitution Θ ::= [] | Θ[X 7→ τ ]

Given a substitution Θ, the satisfiability of Φ under Θ is defined as follows.

• Φ is satisfied under Θ if Φ is >;

• Φ is satisfied under Θ if Φ is T1.= T2 and T1[Θ] = T2[Θ].

• Φ is satisfied under Θ if Φ is Φ1 ∧ Φ2 and both Φ1 and Φ2. are satisfied under Θ

33

34 CHAPTER 9. TYPE RECONSTRUCTION

We say that a type constraint Φ is satisfiable if Φ is satisfiable under some substitution Θ.We first introduce two kinds of judgments; a judgment G ` e ↑ T ⇒ Φ basically means that we

can generate T and Φ for given G and e such that type constraint Φ needs to be solved for typing ewith T under context G; a judgment G ` e ↓ T ⇒ Φ basically states that we can generate Φ for givenG, e and T such that type constraint Φ needs to be solved for typing e with type T under contextG. The rules for a bidirectional type inference algorithm are presented in Figure 9.1 and Figure 9.2.The following theorem establishes the soundness of these rules.

Theorem 31 (Soundness) We have the following.

1. Asume that G ` e ↑ T ⇒ Φ is derivable. If Φ is satisfiable under Θ and dom(Θ) contains allexistential variables in the judgment G ` e ↑ T ⇒ Φ, then G[Θ] ` |e|[Θ] : T [Θ] is derivable.

2. Asume that G ` e ↓ T ⇒ Φ is derivable. If Φ is satisfiable under Θ and dom(Θ) contains allexistential variables in the judgment G ` e ↓ T ⇒ Φ, then G[Θ] ` |e|[Θ] : T [Θ] is derivable.

Proof (1) and (2) are proven simultaneously with structural induction on the derivations D ofG ` e ↑ T ⇒ Φ and G ` e ↓ T ⇒ Φ.

Lemma 32 Let Θ be a substitution on existential variables. We have the following.

1. If G ` e ↑ T ⇒ Φ is derivable, then G[Θ] ` e ↑ T [Θ]⇒ Φ[Θ] is also derivable.

2. If G ` e ↓ T ⇒ Φ is derivable, then G[Θ] ` e ↓ T [Θ]⇒ Φ[Θ] is also derivable.

Proof (1) and (2) are proven simultaneously with structural induction on the derivations of G `e ↑ T ⇒ Φ and G ` e ↓ T ⇒ Φ.

The following theorem establishes the completeness of the presented type inference rules.

Theorem 33 (Completeness) Assume that Γ ` e : τ is derivable. Then we have the following.

1. Γ ` |e| ↑ T ⇒ Φ is derivable for some T and Φ and there exists Θ such that T [Θ] = τ and Φ issatisfiable under Θ.

2. Γ ` |e| ↓ τ ⇒ Φ is derivable for some Φ and Φ is satisfiable.

Proof (1) and (2) are proven simultaneously with structural induction on the derivation of Γ ` e : τ .

9.3 Mutual Recursion

We present both typing rules and type inference rules for handling mutual recursion.

types τ ::= · · · | (τ1, . . . , τn)expressions e ::= · · · | fun f1(x1 : τ1) : τ ′1 is e1 and . . .and fun fn(xn : τn) : τ ′n is en | e#n

9.3. MUTUAL RECURSION 35

G ` b ↑ bool⇒ > (tc-bool-up)

G ` b ↓ T ⇒ T.= bool

(tc-bool-dn)

G ` i ↑ int⇒ > (tc-int-up)

G ` i ↓ T ⇒ T.= int

(tc-int-dn)

G ` x ↑ G(x)⇒ > (tc-var-up)

G ` x ↓ T ⇒ T.= G(x)

(tc-var-dn)

Σ(op) = τ1 ∗ · · · ∗ τn → τ G ` e1 ↓ τ1 ⇒ Φ1 · · · G ` en ↓ τn ⇒ Φn

G ` op(e1, . . . , en) ↑ τ ⇒ Φ1 ∧ · · · ∧ Φn(tc-op-up)

Σ(op) = τ1 ∗ · · · ∗ τn → τ G ` e1 ↓ τ1 ⇒ Φ1 · · · G ` en ↓ τn ⇒ Φn

G ` op(e1, . . . , en) ↓ T ⇒ Φ1 ∧ · · · ∧ Φn ∧ T.= τ

(tc-op-dn)

G ` e ↓ bool⇒ Φ G ` e1 ↑ T ⇒ Φ1 G ` e2 ↓ T ⇒ Φ2

G ` if e then e1 else e2 ↑ T ⇒ Φ ∧ Φ1 ∧ Φ2(tc-if-up)

G ` e ↓ bool⇒ Φ G ` e1 ↓ T ⇒ Φ1 G ` e2 ↓ T ⇒ Φ2

G ` if e then e1 else e2 ↓ T ⇒ Φ ∧ Φ1 ∧ Φ2(tc-if-dn)

G ` e1 ↑ T1 ⇒ Φ1 G ` e2 ↑ T2 ⇒ Φ2

G ` e1, e2 ↑ T1 ∗ T2 ⇒ Φ1 ∧ Φ2(tc-tup-up)

G ` e1 ↓ T1 ⇒ Φ1 G ` e2 ↓ T2 ⇒ Φ2

G ` e1, e2 ↓ T1 ∗ T2 ⇒ Φ1 ∧ Φ2(tc-tup-dn)

G ` e1 ↑ T1 ⇒ Φ1 G ` e2 ↑ T2 ⇒ Φ2

G ` e1, e2 ↓ X ⇒ Φ1 ∧ Φ2 ∧X.= T1 ∗ T2

(tc-tup-dn-atom)

Figure 9.1: Type reconstruction rules for generating types constraints (I)

36 CHAPTER 9. TYPE RECONSTRUCTION

G ` e ↑ T1 ∗ T2 ⇒ ΦG ` e.1 ↑ T1 ⇒ Φ

(tc-fst-up)

G ` e ↑ X ⇒ ΦG ` e.1 ↑ X1 ⇒ Φ ∧X .= X1 ∗X2

(tc-fst-up-atom)

G ` e ↓ T ∗X ⇒ ΦG ` e.1 ↓ T ⇒ Φ

(tc-fst-dn)

G ` e ↑ T1 ∗ T2 ⇒ ΦG ` e.2 ↑ T2 ⇒ Φ

(tc-snd-up)

G ` e ↑ X ⇒ ΦG ` e.2 ↑ X2 ⇒ Φ ∧X .= X1 ∗X2

(tc-snd-up-atom)

G ` e ↓ X ∗ T ⇒ ΦG ` e.2 ↓ T ⇒ Φ

(tc-snd-dn)

G, f : X1 → X2, x : X1 ` e ↓ X2 ⇒ ΦG ` fun f(x) is e ↑ X1 → X2 ⇒ Φ

(tc-fun-up)

G, f : T1 → T2, x : T1 ` e ↓ T2 ⇒ ΦG ` fun f(x) is e ↓ T1 → T2 ⇒ Φ

(tc-fun-dn)

G ` fun f(x) is e ↑ T ⇒ ΦG ` fun f(x) is e ↓ X ⇒ Φ ∧X .= T

(tc-fun-dn-atom)

G, f : τ1 → τ2, x : τ1 ` e ↓ τ2 ⇒ ΦG ` fun f(x : τ1) : τ2 is e ↑ τ1 → τ2 ⇒ Φ

(tc-fun-anno-up)

G, f : τ1 → τ2, x : τ1 ` e ↓ τ2 ⇒ ΦG ` fun f(x : τ1) : τ2 is e ↓ T ⇒ Φ ∧ T = τ1 → τ2

(tc-fun-anno-dn)

G ` e1 ↑ T1 → T2 ⇒ Φ1 G ` e2 ↓ T1 ⇒ Φ2

G ` app(e1, e2) ↑ T2 ⇒ Φ1 ∧ Φ2(tc-app-up)

G ` e1 ↑ X1 ⇒ Φ1 G ` e2 ↑ T ⇒ Φ2

G ` app(e1, e2) ↑ X2 ⇒ Φ1 ∧ Φ2 ∧X1 = T → X2(tc-app-up-atom)

G ` app(e1, e2) ↑ T2 ⇒ ΦG ` app(e1, e2) ↓ T1 ⇒ Φ ∧ T1

.= T2(tc-app-dn)

G ` e1 ↑ T1 ⇒ Φ1 G, x : T1 ` e2 ↑ T2 ⇒ Φ2

G ` let x = e1 in e2 ↑ T2 ⇒ Φ1 ∧ Φ2(tc-let-up)

G ` e1 ↑ T1 ⇒ Φ1 G, x : T1 ` e2 ↓ T2 ⇒ Φ2

G ` let x = e1 in e2 ↓ T2 ⇒ Φ1 ∧ Φ2(tc-let-dn)

G ` e ↓ τ ⇒ ΦG ` (e : τ) ↑ τ ⇒ Φ

(tc-anno-up)

G ` e ↓ τ ⇒ ΦG ` (e : τ) ↓ T ⇒ Φ ∧ τ .= T

(tc-anno-dn)

Figure 9.2: Type reconstruction rules for generating types constraints (II)

9.3. MUTUAL RECURSION 37

The type (τ1, . . . , τn) is for an expression that defines n functions mutually recursively and thesefunctions are of types τ1, . . . , τn, respectively.

Γ,f1:τ1→τ ′1,...,fn:τn→τ ′n,x1:τ1`e1:τ ′1...

Γ,f1:τ1→τ ′1,...,fn:τn→τ ′n,xn:τn`en:τ ′n

Γ`fun f1(x1:τ1):τ ′1 is e1 and...and fun fn(xn:τn):τ ′n is en):(τ1→τ ′1,...,τn→τ′n)

(type-funs)

Γ ` e : (τ1, . . . .τn) 1 ≤ i ≤ nΓ ` e#i : τi

(type-choose)

Γ,f1:τ1→τ ′1,...,fn:τn→τ ′n,x1:τ1`e1↓τ ′1⇒Φ1

...Γ,f1:τ1→τ ′1,...,fn:τn→τ ′n,xn:τn`en↓τ ′n⇒Φn

Γ`fun f1(x1:τ1):τ ′1 is e1 and...and fun fn(xn:τn):τ ′n is en)↑(τ1→τ ′1,...,τn→τ′n)⇒Φ1∧...∧Φn

(tc-funs-anno-up)

Γ,f1:X1→X′1,...,fn:Xn→Xn,x1:X1`e1↓X′1⇒Φ1

...Γ,f1:X1→X′1,...,fn:Xn→X′n,xn:Xn`en↓X′n⇒Φn

Γ`fun f1(x1) is e1 and...and fun fn(xn) is en)↑(X1→X′1,...,Xn→X′n)⇒Φ1∧...∧Φn

(tc-funs-up)

G ` e ↑ (T1, . . . , Tn)⇒ Φ 1 ≤ i ≤ nG ` e#i ↑ Ti ⇒ Φ

(tc-choose-up)

G ` e ↑ (T1, . . . , Tn)⇒ Φ 1 ≤ i ≤ nG ` e#i ↓ T ⇒ Φ ∧ T = Ti

(tc-choose-dn)

Notice that neither rule (tc-funs-dn) nor rule (tc-funs-anno-dn) is presented. There is probablyno need for such rules in practice. In case there is such a need, we can always use either rule(tc-funs-up) or rule (tc-funs-anno-up) to synthesize a type and then form a type constraintbetween the synthezied type and the type being checked against.