<<

Type Systems for Programming Languages

Benjamin . Pierce

bcÔieÖce@ci׺ÙÔeÒÒºedÙ

Working draft of January 15, 2000

This is preliminary draft of a book in progress. Comments, suggestions, and corrections are welcome. Contents

Preface 8

1 Introduction 13 1.1 What is a ? ...... 13 1.2 A Brief History of Type ...... 14 1.3 Applications of Type Systems ...... 16 1.4 Related Reading ...... 16

2 Mathematical Preliminaries 18 2.1 Sets and Relations ...... 18 2.2 Induction ...... 18 2.3 Term Rewriting ...... 19

3 Untyped Arithmetic Expressions 20 3.1 ...... 20 Syntax ...... 21 Evaluation ...... 21 3.2 Formalities ...... 21 Syntax ...... 21 Evaluation ...... 25 3.3 Properties ...... 27 3.4 Implementation ...... 27 Syntax ...... 27 Evaluation ...... 28 3.5 Summary ...... 28 3.6 Further Reading ...... 30

4 The Untyped Lambda-Calculus 31 4.1 Basics ...... 32 Syntax ...... 33 Operational Semantics ...... 34 4.2 Programming in the Lambda-Calculus ...... 34

1 4.3 Is the Lambda-Calculus a ? ...... 39 4.4 Formalities ...... 39 Syntax ...... 39 Substitution ...... 40 Operational Semantics ...... 43 Summary ...... 43 4.5 Further Reading ...... 44

5 Implementing the Lambda-Calculus 45 5.1 Nameless Representation of Terms ...... 45 Syntax ...... 46 Shifting and Substitution ...... 48 Evaluation ...... 49 5.2 A Concrete Realization ...... 49 Syntax ...... 50 Shifting and Substitution ...... 50 Evaluation ...... 51 5.3 Ordinary vs. Nameless Representations ...... 51

6 Typed Arithmetic Expressions 52 6.1 Syntax ...... 52 6.2 The Typing Relation ...... 52 6.3 Properties of Typing and Reduction ...... 53 Typing Derivations ...... 53 Typechecking ...... 54 Safety = Preservation + Progress ...... 54 6.4 Implementation ...... 55 6.5 Summary ...... 56

7 Simply Typed Lambda-Calculus 58 7.1 Syntax ...... 58 7.2 The Typing Relation ...... 59 7.3 Summary ...... 61 7.4 Properties of Typing and Reduction ...... 62 Typechecking ...... 62 Typing and Substitution ...... 64 Type Soundness ...... 64 7.5 Implementation ...... 65 7.6 Further Reading ...... 66 8 Extensions 67 8.1 Base Types ...... 67 8.2 ...... 67 8.3 Let bindings ...... 68 8.4 Records and Tuples ...... 68 8.5 Variants ...... 72 8.6 General recursion ...... 72 8.7 Lists ...... 73 8.8 Lazy records and let-bindings ...... 75

9 References 76 9.1 Further Reading ...... 79

10 Exceptions 80 10.1 Errors ...... 80 10.2 Exceptions ...... 80

11 Type Equivalence 81

12 Definitions 83 12.1 Type Definitions ...... 83 12.2 Term Definitions ...... 85

13 86 13.1 The Subtype Relation ...... 87 Variance ...... 88 Summary ...... 89 13.2 Metatheory of Subtyping ...... 91 Algorithmic Subtyping ...... 91 Minimal Typing ...... 92 13.3 Implementation ...... 96 13.4 Meets and Joins ...... 97 13.5 Primitive Subtyping ...... 99 13.6 The ...... 99 13.7 Other stuff ...... 99

14 Imperative Objects 100 14.1 Objects ...... 100 14.2 Object Generators ...... 102 14.3 Subtyping ...... 103 14.4 Basic classes ...... 104 14.5 Extending the Internal State ...... 105 14.6 Classes with “Self” ...... 106 15 Recursive Types 109 15.1 Examples ...... 109 Lists ...... 109 Hungry Functions ...... 109 Recursive Values from Recursive Types ...... 110 Untyped Lambda-Calculus, Redux ...... 110 Recursive Objects ...... 112 15.2 Equi-recursive Types ...... 112 ML Implementation ...... 114 15.3 Iso-recursive Types ...... 115 15.4 Subtyping and Recursive Types ...... 116

16 Case Study: Featherweight Java 117

17 Type Reconstruction 118 17.1 Substitution ...... 118 17.2 Universal vs. Existential Type Variables ...... 119 17.3 Constraint-Based Typing ...... 121 17.4 Unification ...... 125 17.5 Principal Typings ...... 128 17.6 Further Reading ...... 129

18 Universal Types 130 18.1 Motivation ...... 130 18.2 Varieties of Polymorphism ...... 131 18.3 Definitions ...... 132 18.4 Examples ...... 135 Warm-ups ...... 135 Polymorphic Lists ...... 136 Impredicative Encodings ...... 136 18.5 Metatheory ...... 139 Soundness ...... 139 Strong Normalization ...... 139 Erasure and Typeability ...... 140 Type Reconstruction ...... 141 18.6 Implementation ...... 141 Nameless Representation of Types ...... 141 ML Code ...... 141 18.7 Further Reading ...... 143 19 Existential Types 144 19.1 Motivation ...... 144 19.2 Data Abstraction with Existentials ...... 149 Abstract Data Types ...... 149 Existential Objects ...... 152 Objects vs. ADTs ...... 154 19.3 Encoding Existentials ...... 154 19.4 Implementation ...... 156 19.5 Historical Notes ...... 156

20 Bounded Quantification 157 20.1 Motivation ...... 157

20.2 Definitions ...... 159 :

Kernel < ...... 159 : Full F< ...... 162 20.3 Examples ...... 163 Encoding Products ...... 163 Encoding Records ...... 163 Church Encodings with Subtyping ...... 165 20.4 Safety ...... 167 20.5 Bounded Existential Types ...... 171 20.6 Historical Notes and Further Reading ...... 171

21 Implementing Bounded Quantification 173 21.1 Promotion ...... 173 21.2 Minimal Typing ...... 174

F

21.3 Subtyping in <: ...... 176

f F

21.4 Subtyping in <: ...... 179 : 21.5 Undecidability of Subtyping in Full F < ...... 181

22 Denotational Semantics 185 22.1 Types as Subsets of the Natural Numbers ...... 186

The Universe of Natural Numbers ...... 186 : Subset Semantics for F < ...... 187 Problems with the Subset Semantics ...... 190 22.2 The PER interpretation ...... 190 Interpretation of Types ...... 191 Applications of the PER model ...... 192 Digression on full abstraction ...... 196 22.3 General Recursion and Recursive Types ...... 196 Continuous Partial Orders ...... 196 The CUPER Interpretation ...... 200 Interpreting Recursive Types ...... 201 22.4 Further Reading ...... 203

23 Polymorphic Update 204

24 Type Operators and Kinding 206 24.1 Intuitions ...... 206 24.2 Definitions ...... 209

25 Higher-Order Polymorphism 213 25.1 Higher-Order Universal Types ...... 213 25.2 Higher-Order Existential Types ...... 215 25.3 Type Equivalence and Reduction ...... 218 25.4 Soundness ...... 218

26 Implementing Higher-Order Systems 221

27 Higher-Order Subtyping 224

28 Pure Objects and Classes 228 28.1 Simple Objects ...... 228 28.2 Subtyping ...... 229 28.3 Types ...... 230 28.4 Sending Messages to Objects ...... 230 28.5 Simple Classes ...... 231 28.6 Adding Instance Variables ...... 232 28.7 Classes with “Self” ...... 234 28.8 Class Types ...... 235 28.9 Generic Inheritance ...... 235

29 Structures and Modules 238 29.1 Basic Structures ...... 238 29.2 Record Kinds and Subkinding ...... 242 29.3 Singleton Kinds ...... 244 29.4 Dependent Function and Record Kinds ...... 245 29.5 Dependent Record Expressions and Records of Types ...... 246 29.6 Higher- Singletons ...... 247 29.7 First-class Substructures and Functors ...... 248 29.8 Second-Class Modules ...... 250 29.9 Other points to make ...... 250

30 Planned Chapters 251 Appendices 253

A Solutions to Selected Exercises 253

B Summary of Notation 266 .1 Metavariable Conventions ...... 266 B.2 Rule Naming Conventions ...... 266

C Suggestions for Larger Projects 268 C.1 Objects ...... 268 C.2 Encodings of Logics ...... 269 C.3 ...... 270 C.4 Other Type Systems ...... 270 C.5 Sources for Additional Ideas ...... 271

D Bluffers Guide to OCaml 272

E Running the Checkers 273 .1 Preparing Your Input ...... 273 E.2 Ascii Equivalents ...... 273 E.3 Running the Checker ...... 274 E.4 Compiling the Checkers ...... 274 E.5 Objective ...... 274

Bibliography 275

Index 288 Preface

The study of type systems for programming languages has emerged over the past decade as one of the most active areas of science research, with impor- tant applications in software engineering, programming language design, high- performance implementation, and security of information networks. This text aims to introduce the area to beginning graduate students and ad- vanced undergraduates. A broad range of core topics are covered in detail, includ- ing simple type systems, type reconstruction, universal and existential polymor- phism, subtyping, bounded quantification, recursive types, and type operators. Early chapters on the untyped lambda-calculus help make the book self-contained, allowing it to be used in courses for students with no background in the theory of programming languages. The book adopts a strongly pragmatic approach throughout: a typical chapter begins with programming examples motivating a new typing feature, develops the feature and its metatheory, adduces typechecking algorithms, and illustrates these with executable ML typecheckers. The underlying semantic formalism is almost entirely operational, for a close correspondence with familiar programming languages. A repeated theme is the theoretical properties required to build sound and com- plete typechecking algorithms. Both the proofs and the algorithms themselves are presented in detail. Moreover, each chapter is accompanied by a running im- plementation that can be used as a basis for experimentation by students, class projects, etc.

Audience

The book is aimed at graduate students, including both the general graduate pop- ulation as well as students intending to specialize in programming language re- search. For the former, it should serve to introduce a number of key ideas from the design and analysis of programming languages, with type systems as an or- ganizing structure. For the latter, it should provide sufficient background to pro- ceed directly on to the research literature. The book is suitable for self-study by

8 January 15, 2000 PREFACE 9 researchers in other areas who want to learn something about type systems, and should be a useful reference for experts. The first several chapters should be usable in upper-division undergraduate courses.

Goals

The mail goals of the book are:

¯ Accessibility. A reader should be able to approach the book with little or no background in theory of programming languages.

¯ Coverage of core topics. By the end of the book, the reader should fully equipped to tackle the research literature in type systems.

¯ Pragmatism. The book stays as close as possible to programming languages (sometimes at the expense of topics that might be included in a book written from the perspective of typed lambda-calculi and logic). In particular, the underlying computational substrate is a call-by-value lambda-calculus.

¯ Diversity. The book tries to show the leafiness of the topic rather than trying to unify all the threads addressed in the book. (Of course, I’ve unified as many of the threads as I could manage.)

¯ Honesty. Every type system discussed in the book must be implemented. Every example must run. To achieve all this, a few other desirable properties have been sacrificed.

¯ Completeness of coverage (probably impossible in one book, certainly in a textbook).

¯ Efficiency (as opposed to termination) of the typechecking algorithms de- scribed. This is not a book about industrial-strength typechecker implemen- tation.

Required Background

No background in the theory of programming languages is assumed, but students should should approach the book with a degree of prior mathematical maturity (in particular, rigorous undergraduate coursework in discrete mathematics, algo- rithms, and elementary logic). Readers should also be familiar with some higher-order functional program- ming language (Scheme, ML, Haskell, etc.), and basic concepts of programming languages and (abstract syntax, Backus-Naur grammars, evaluation, ab- stract machines, etc.). This material is available in many excellent undergraduate texts. I particularly like the one by Friedman, Wand, and Haynes [FWH92]. January 15, 2000 PREFACE 10

Course Outlines

In an advanced graduate course, it should be possible to cover essentially the whole book in a semester. For an undergraduate or beginning graduate course, there are two basic paths through the material:

¯ type systems in programming (omitting implementation chapters), and

¯ basic theory and implementation (omitting or skimming the end of the book). Shorter courses can also be constructed by selecting particular chapters of interest. In a course where term projects are a major part of the work, it may be desir- able to postpone some of the theoretical material (e.g., denotational semantics, and perhaps some of the deeper chapters on implementation) so that a broad range of examples can be covered before the point where students have to choose project topics.

Chapter Dependencies

The major dependencies between chapters are outlined in Figure 1. Solid lines indicate that the later chapter is best read after the earlier. Dotted lines mean that the chapters can be read out of order except for some sections.

Typographic Conventions

Most chapters develop the features of some type system in a discursive way, then define the system formally as a collection of inference rules with brackets above and below to them off from the surrounding text. For the sake of completeness, these definitions are usually presented in full, including not only the new rules for the features under discussion at the moment, but also the rest of the rules needed to constitute a complete calculus. The new parts are set on a gray background to make the “delta” from previous systems visually obvious. An unusual feature of the book’ production is that all the examples are me- chanically checked during typesetting: an automatic script goes through each chap- ter, extracts the examples, generates and compiles a custom typechecker contain- ing just the features under discussion, applies it to the examples, and inserts the checker’s responses in the text. The system that does the hard parts of this, called TinkerType, was developed by Michael Levin and myself [LP99].

Electronic resources

A collection of implementations for the typecheckers and interpreters described in

ÙÔeÒÒºedÙ»~bcÔieÖce»ØÝÔe×bÓÓk the text is available at hØØÔ:»»ÛÛÛºci׺ . These January 15, 2000 PREFACE 11

2

3

4

6

5

7.5

7

8 11 17 18

24

10 12 19

9 20.6

13 20 25

15.4

14 15 21 23 27

22.3

16 22 28 26

Figure 1: Chapter dependencies January 15, 2000 PREFACE 12 implementations have been carefully polished for readability and modifiability, and have been used very successfully by my students as the basis of both small im-

plementation exercises and larger course projects. The implementation language is

iaºfÖ the Objective Caml dialect of ML, freely available through hØØÔ:»»caÑкiÒÖ .

Corrections for any errors discovered in the text will also be made available at

ÔeÒÒºedÙ»~bcÔieÖce»ØÝÔe×bÓÓk hØØÔ:»»ÛÛÛºci׺٠.

Acknowledgements

Many! Chapter 1

Introduction

Proofs of programs are too boring for the social process of mathematics to work. — Richard DeMillo, Richard Lipton, and Alan Perlis [DLP79]

...So don’ rely on social processes for verification. — David Dill

Despite decades of concern in both industry and academia, expensive failures of large software projects are common. Proposed approaches to improving software quality include—among other ideas—a broad spectrum of techniques for helping ensure that a software system behaves correctly with respect to some specifica- tion, implicit or explicit, of its desired behavior. On one end of this spectrum are powerful frameworks such as algebraic specification languages, modal logics, and denotational semantics; these can be used to express very general correctness prop- erties but are cumbersome to use and demand significant involvement by the pro- grammer not only in the application domain but also in the formal subtleties of the framework itself. At the other end are techniques of much more limited power—so limited that they can be built into compilers or linkers and thus “applied” even by programmers unfamiliar with the underlying theories. Such methods often take the form of type systems.

1.1 What is a Type System?

Type systems are generally formulated as collections of rules for checking the “con- sistency” of programs. This kind of checking exposes not only trivial mental slips, but also deeper conceptual errors, which frequently manifest as type errors. A useful—though rough—distinction divides the world of programming lan- guages into two parts:

13 January 15, 2000 1. INTRODUCTION 14

¯ Untyped — programs simply execute flat out; there is no attempt to check “consistency of shapes”

¯ Typed — some attempt is made, either at or at run-time, to check shape-consistency

Among typed languages, we can break things down further:

Statically checked Dynamically checked Strongly typed ML, Haskell, Pascal (almost), Lisp, Scheme Java (almost) Weakly typed C, C++

1.2 A Brief History of Type

The following table presents a (rough and incomplete) chronology of some impor- tant high points in the history of type systems in . Related devel- opments in logic are also included (in italics), to give a sense of the importance of this field’s contributions. late 1800s Origins of formal logic [?] early 1900s Formalization of mathematics [WR25] 1930s Untyped lambda-calculus [Chu41] 1940s Simply typed lambda-calculus [Chu40, CF58] 1950s [Bac81] 1950s Algol [N · 63] 1960s Automath project [dB80] 1960s [BDMN79] 1970s Martin-L¨of [Mar73, Mar82, SNP90] 1960s Curry-Howard isomorphism [How80] 1970s , F ! [Gir72] 1970s polymorphic lambda-calculus [Rey74] 1970s CLU [LAB · 81] 1970s polymorphic type inference [Mil78, DM82] 1970s ML [GMW79] 1970s intersection types [CDC78, CDCS79, Pot80] 1980s NuPRL project [Con86] 1980s subtyping [Rey80, Car84, Mit84a] 1980s ADTs as existential types [MP88] 1980s calculus of constructions [Coq85, CH88] 1980s [Gir87, GLT89] 1980s bounded quantification [CW85, CG92, CMMS94] January 15, 2000 1. INTRODUCTION 15

1980s Edinburgh Logical Framework [HHP92] 1980s Forsythe [Rey88] 1980s pure type systems [Bar92a] 1980s dependent types and modularity [Mac86] 1980s Quest [Car91] 1980s Extended Calculus of Constructions [Luo90] 1980s Effect systems [?, TJ92, TT97] 1980s row variables and extensible records [Wan87, ´em89, CM91] 1990s higher-order subtyping [Car90, CL91, PT94] 1990s typed intermediate languages [TMC · 96] 1990s Object Calculus [AC96] 1990s translucent types and modarity [HL94, Ler94] 1990s typed assembly language [MWCG98]

In computer science, the earliest type systems, beginning in the 1950s (e.g., FORTRAN), were used to improve efficiency of numerical calculations by distin- guishing between natural-number-valued variables and arithmetic expressions and real-valued ones, allowing the compiler to use different representations and gen- erate appropriate machine instructions for arithmetic operations. In the late 1950s and early 1960s (e.g., ALGOL), the classification was extended to structured data (arrays of records, etc.) and higher-order functions. Beginning in the 1970s, these early foundations have been extended in many directions...

¯ allows a single term to be used with many differ- ent types (e.g., the same sorting routine might be used to sort lists of natural numbers, lists of reals, lists of records, etc.), encouraging code reuse;

¯ module systems support programming in the large by providing a frame- work for defining (and automatically checking) interfaces between the parts of a large software system;

¯ subtyping and object types address the special needs of object-oriented pro- gramming styles;

¯ connections are being developed between the type systems of programming languages, the specification languages used in program verification, and the formal logics used in theorem proving. All of these (among many others) are still areas of active research. I’ like to include here a longer discussion of the historical origins of various ideas in type systems. This is usually how I use the whole first lecture of my graduate course, and it goes down very well, but to put it all in writing will require a of research. January 15, 2000 1. INTRODUCTION 16

1.3 Applications of Type Systems

Beyond their traditional benefits of robustness and efficiency, type systems play an increasingly central role in computer and network security: static typing lies at the core of the security models of Java and JINI, for example, and is the main enabling technology for Proof-Carrying Code. Type systems are used to organize compilers, verify protocols, structure information on the web, and even model natural languages. Short sketches of some of these diverse applications...

¯ In programming in the large (module systems, interface definition languages, etc.)

¯ In compiling and optimization (static analyses, typed intermediate languages, typed assembly languages, etc.)

¯ In “self-certification” of untrusted code (so-called “proof-carrying code” [NL96, Nec97, NL98])

¯ In security

¯ In theorem proving

¯ In databases

¯ In linguistics (categorial grammar [Ben95, vBM97, etc.] , and maybe something seminal by Lambek)

¯ In Y2K conversion tools

¯ DTDs and other “web metadata” (note from Henry Thompson: DTDs were origi- nally designed for SGML because of the expense of cancelling huge typesetting runs due to errors in the markup!)

1.4 Related Reading

While this book attempts to be self contained, it is far from comprehensive: the area is too large, and can be approached from too many angles, to do it justice in one book. Here are a few other good entry points:

¯ Handbook articles by Cardelli [Car96] and Mitchell [Mit90] offer quick intro- ductions to the area. Barendregt’s article [Bar92b] is for the more mathemat- ically inclined.

¯ Mitchell’s massive textbook on programming languages [Mit96] covers basic , a range of type systems, and many aspects of semantics. January 15, 2000 1. INTRODUCTION 17

¯ Abadi and Cardelli’s A Theory of Objects [AC96] develops much of the same material as this present book, de-emphasizing implementation aspects and concentrating instead on the application of these ideas in a foundation treat- ment of object-oriented programming. Kim Bruce’s forthcoming Foundations of Object-Oriented Programming Languages will cover similar ground. Intro- ductory material on object-oriented type systems can also be found in [PS94, Cas97].

¯ Reynolds [Rey98] Theories of Programming Languages, a graduate-level survey of the theory of programming languages, includes beautiful expositions of polymorphic typing and intersection types.

¯ Girard’s Proofs and Types [GLT89] treats logical aspects of type systems (the Curry-Howard isomorphism, etc.) thoroughly. It also includes a description of System F from its creator, and an appendix introducing linear logic.

¯ The Structure of Typed Programming Languages, by Schmidt [?], develops core concepts of type systems in the context of programming language design, including several chapters on conventional imperative languages. Simon Thompson’s Type Theory and [Tho91] focuses on con- nections between functional programming (in the “pure functional program- ming” sense of Haskell or Miranda) and constructive type theory, viewed from a logical perspective.

¯ Semantic foundations for both untyped and typed languages are covered in depth in textbooks by Gunter [Gun92] and Winskel [Win93].

¯ Hindley’s monograph Basic Simple Type Theory [Hin97] is a wonderful com- pendium of results about the simply typed lambda-calculus and closely re- lated systems. Its coverage is deep rather than broad.

If you want a single book besides the one you’re holding, I’d recommend either Mitchell or Abadi and Cardelli. Chapter 2

Mathematical Preliminaries

This chapter mostly still needs to be written. I do not intend to go into a great deal of detail (a student that needs a real introduction to these topics is going to be lost in a couple of chapters anyway) — just remind the reader of basic concepts and notations.

Before getting started, we need to establish some common notation and state a few basic mathematical facts. Most readers should be able to skim this chapter and refer back to it as necessary.

2.1 Sets and Relations 2.2 Induction

2.2.1 Definition: A partially ordered set Ë is said to be well founded if it contains

× ;× ;× ; :::

¾ ¿

no infinite decreasing chains—that is, if there is no infinite sequence ½

Ë × × ¾

·½ i of elements of such that each i is strictly less than .

2.2.2 Theorem [Principle of well-founded induction]: Suppose that the set Ë is Ë

well founded and that È is some predicate on the elements of . If we can show,

¼ ¼

: Ë ´8× <×:È´× µµ È ´×µ È ´×µ

for each × , that implies , then we may conclude that

: Ë ¾ holds for every × .

2.2.3 Corollary [Principle of induction on the natural numbers]: Suppose that È

´8i<

is some predicate on the natural numbers. If we can show, for each Ñ, that

´iµµ È ´Ñµ È ´Òµ Ò ¾ Ñ: È implies , then we may conclude that holds for every .

Proof: The set of natural numbers is well founded. ¾

18 January 15, 2000 2. MATHEMATICAL PRELIMINARIES 19

2.2.4 Corollary [Principle of lexicographic induction]: Define the following “dic-

¼ ¼ ¼

Ñ; Òµ < ´Ñ ;Ò µ Ñ < Ñ

tionary ordering” on pairs of natural numbers: ´ iff or

¼ ¼

= Ñ Ò<Ò Ñ and .

Now, suppose that È is some predicate on pairs of natural numbers. If we can

¼ ¼ ¼ ¼

Ñ; Òµ ´8´Ñ ;Ò µ < ´Ñ; Òµ: È ´Ñ ;Ò µµ È ´Ñ; Òµ

show, for each ´ , that implies , then

´Ñ; Òµ ´Ñ; Òµ we may conclude that È holds for every pair . (A similar principle holds for lexicographically ordered triples, quadruples,

etc.) ¾

Proof: The lexicographic ordering on pairs of numbers is well founded. ¾

2.3 Term Rewriting

(or maybe this material should be folded into the next chapter...) Chapter 3

Untyped Arithmetic Expressions

Quite a bit of text and a few technical definitions are still missing here. The idea is to introduce the basic ideas of defining a language and its operational semantics formally, and proving some simple properties by structural induction, before getting to the complexities (esp. name binding) of the full-blown lambda-calculus.

3.1 Basics

We begin with a very simple language for calculating with numbers and booleans.

ØÖÙe;

Á

ØÖÙe

if faÐ×e ØheÒ ØÖÙe eÐ×e faÐ×e;

Á

faÐ×e

¼;

Á

¼

×Ùcc ´×Ùcc ´×Ùcc ¼µµ;

Á

¿

×Ùcc ´ÔÖed ¼µ;

Á

½

i×ÞeÖÓ ´ÔÖed ´×Ùcc ¼µµ;

20

January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 21

Á

ØÖÙe

i×ÞeÖÓ ´×Ùcc ´×Ùcc ¼µµ;

Á faÐ×e

Throughout the book, the symbol Á will be used to display the results of - uating examples. You can think of the lines marked with Á as the responses from an interactive when presented with the preceding inputs.

For brevity, the examples use standard arabic numerals as shorthand for nested

¼ ×Ùcc´×Ùcc´×Ùcc´¼µµµ ¿ applications of ×Ùcc to , writing as .

Syntax

The syntax of arithmetic expressions comprises several kinds of terms. The con-

faÐ×e ¼ Ø ×Ùcc Ø ÔÖed Ø

stants ØÖÙe, , and are terms. If is a term, then so are , , and

i×ÞeÖÓ Ø Ø Ø Ø if Ø ØheÒ Ø eÐ×e Ø

¾ ¿ ½ ¾ ¿ . Finally, if ½ , , and are terms, then so is . These forms are summarized in the following abstract grammar:

Ø ::= (terms...)

ØÖÙe constant true

faÐ×e constant false

Ø ØheÒ Ø eÐ×e Ø if conditional

¼ constant zero Ø

×Ùcc successor Ø

ÔÖed predecessor Ø i×ÞeÖÓ zero test

Evaluation 3.2 Formalities

Syntax

3.2.1 Definition [Terms]: The set of terms is the smallest set Ì such that

ØÖÙe; faÐ×e; ¼g Ì

1. f ;

Ø ¾Ì f×Ùcc Ø ; ÔÖed Ø ; i×ÞeÖÓ Ø g Ì

½ ½ ½

2. if ½ , then ;

Ø ¾Ì Ø ¾Ì Ø ¾Ì if Ø ØheÒ Ø eÐ×e Ø ¾Ì

¾ ¿ ½ ¾ ¿ 3. if ½ , , and , then . These three clauses capture exactly what is meant by the productions in the more

concise and readable “abstract grammar” notation that we used above. ¾ January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 22

Definition 3.2.1 is an example of an inductive definition. Since inductive defi- nitions are ubiquitous in the study of programming languages, it is worth pausing for a moment to examine this one in detail. Here is an alternative definition of the same set, in a more concrete style.

3.2.2 Definition [Terms, more concretely]: For each natural number i, define a set Ë

i as follows:

Ë = ;

¼

Ë = fØÖÙe; faÐ×e; ¼g

i·½

[ f×Ùcc Ø ; ÔÖed Ø ; i×ÞeÖÓ Ø jØ ¾Ë g

½ ½ ½ ½ i

[ fif Ø ØheÒ Ø eÐ×e Ø j Ø ; Ø ; Ø ¾Ë g:

½ ¾ ¿ ½ ¾ ¿ i

Finally, let

[

Ë = Ë :

i

i

Ë Ë Ì

½ ¾

That is, ¼ is empty; contains just the constants; contains the constants plus

ÔÖed i×ÞeÖÓ

the phrases that can be built with constants and just one ×Ùcc, , ,or

if Ë ×Ùcc ÔÖed i×ÞeÖÓ

; ¿ contains these plus all phrases that can be built using , , ,

if Ë Ë and on phrases in ¾ ; and so on. collects together all the phrases that can be built in this way—i.e., all phrases built by some finite number of applications and

abstractions, beginning with just variables. ¾

Ë ¾

3.2.3 Exercise [Quick check]: List the elements of ¿ .

Ë i

3.2.4 Exercise: Show that the sets i are cumulative—that is, that for each we

Ë Ë ¾

i·½ have i .

Now let us check that the two definitions of terms actually define the same set.

We’ll do the proof in quite a bit of detail, to show how all the pieces fit together.

= Ë ¾ 3.2.5 Proposition: Ì .

Proof: Ì was defined as the smallest set satisfying certain conditions. So it suffices

to show (a) that Ë satisfies these conditions, and (b) that any set satisfying the Ë conditions has Ë as a subset (i.e., that is the smallest set satisfying the conditions).

For part (a), we must check that each of the three conditions in Definition 3.2.1

Ë

Ë Ë = fØÖÙe; faÐ×e; ¼g Ë  Ë

½ i

holds of . First, since ½ and , it is clear that the

i

Ë

Ë Ë Ø ¾Ë Ë = i

constants are in . Second, if ½ , then (since ) there must be some

i

i Ø ¾Ë Ë ×Ùcc Ø ¾

i i·½ ½

such that i . But then, by the definition of , we must have

Ë ×Ùcc Ø ¾Ë ÔÖed Ø ¾Ë i×ÞeÖÓ Ø ¾Ë

·½ ½ ½ ½

i , hence ; similarly, we see that and .

Ø ¾ Ë Ø ¾ Ë Ø ¾ Ë if Ø ØheÒ Ø eÐ×e Ø ¾ Ë

¾ ¿ ½ ¾ ¿ Third, if ½ , , and , then ,bya

similar argument. ¼

For part (b), suppose that some set Ë satisfies the three conditions in Defini-

¼

Ò Ë  Ë tion 3.2.1. We will argue, by induction on , that every Ò , from which it

January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 23

¼ ¼

Ë  Ë Ë  Ë Ñ < Ò

will clearly follow that . Suppose that Ñ for all ; we must

¼

Ë Ë Ë Ò = ¼ Ò

then show that Ò . Since the definition of has two clauses (for and

= i · ½

Ò ), there are two cases to consider.

¼

¯ Ò = ¼ Ë = ; ;Ë

If , then Ò . But trivially.

¯ Ò = i · ½ i Ø Ë Ë

·½ i·½ Otherwise, for some . Let be some element of i . Since

is defined as the union of three smaller sets, Ø must come from one of these

sets, and there are three possibilities to consider:

¼

Ø ¾Ë

1. Ø is a constant, hence by condition (1).

Ø ×Ùcc Ø ÔÖed Ø i×ÞeÖÓ Ø Ø ¾Ë

½ ½ ½ i

2. has the form ½ , ,or , for some . But

¼

Ø ¾ Ë

then, by the induction hypothesis, ½ , and so, by condition (2),

¼ ¾Ë

Ø .

Ø if Ø ØheÒ Ø eÐ×e Ø Ø ; Ø ; Ø ¾Ë

¾ ¿ ½ ¾ ¿ i

3. has the form ½ , for some . Again,

¼

Ø Ø Ø Ë

¾ ¿ by the induction hypothesis, ½ , , and are all in , and hence, by

condition (3), so is Ø.

¼

Ë Ë Ë

Thus, we have shown that each i . By the definition of as the union of all

¼

Ë ËË ¾ the i , this gives , completing the argument.

The explicit characterization of Ì justifies an important principle for reasoning

¾ Ì Ø about its elements. If Ø , then one of three things must be true about —either

1. Ø is a constant, or

Ø ×Ùcc Ø ÔÖed Ø i×ÞeÖÓ Ø Ø

½ ½ ½

2. has the form ½ , ,or for some smaller term ,or

Ø if Ø ØheÒ Ø eÐ×e Ø Ø Ø Ø

¾ ¿ ½ ¾ ¿ 3. has the form ½ for some smaller terms , , and . We can put this observation to work in two ways: we can give inductive definitions of functions over the set of terms, and we can give inductive proofs of properties of

terms. For example, here is a simple inductive definition of a function mapping Ø

each term Ø to the set of constants used in .

´Øµ 3.2.6 Definition: The set of constants appearing in a term Ø, written Consts ,is

defined as follows:

ØÖÙeµ = fØÖÙeg

Consts ´

faÐ×eµ = ffaÐ×eg

Consts ´

i×ÞeÖÓµ = fi×ÞeÖÓg

Consts ´

´×Ùcc Ø µ = ´Ø µ ½

Consts ½ Consts

´ÔÖed Ø µ = ´Ø µ ½

Consts ½ Consts

´i×ÞeÖÓ Ø µ = ´Ø µ ½

Consts ½ Consts

´if Ø ØheÒ Ø eÐ×e Ø µ = ´Ø µ [ ´Ø µ [ ´Ø µ ¾

¾ ¿ ½ ½ ½ Consts ½ Consts Consts Consts January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 24

Another property of terms that can be calculated by an inductive defintion is

their size.

´Øµ

3.2.7 Definition: The size of a term Ø, written size , is defined as follows:

ØÖÙeµ = ½

size ´

faÐ×eµ = ½

size ´

i×ÞeÖÓµ = ½

size ´

´×Ùcc Ø µ = ´Ø µ·½ ½

size ½ size

´ÔÖed Ø µ = ´Ø µ·½ ½

size ½ size

´i×ÞeÖÓ Ø µ = ´Ø µ·½ ½

size ½ size

´if Ø ØheÒ Ø eÐ×e Ø µ = ´Ø µ· ´Ø µ· ´Ø µ·½

¾ ¿ ½ ½ ½ size ½ size size size

That is, the size of Ø is the number of nodes in its abstract syntax tree. Similarly,

´Øµ

the depth of a term Ø, written depth , is defined as follows:

ØÖÙeµ = ½

depth´

faÐ×eµ = ½

depth´

i×ÞeÖÓµ = ½

depth´

´×Ùcc Ø µ = ´Ø µ·½ ½

depth ½ depth

´ÔÖed Ø µ = ´Ø µ·½ ½

depth ½ depth

´i×ÞeÖÓ Ø µ = ´Ø µ·½ ½

depth ½ depth

´if Ø ØheÒ Ø eÐ×e Ø µ = ´ ´Ø µ; ´Ø µ; ´Ø µµ · ½

¾ ¿ ½ ½ ½

depth ½ max depth depth depth

´Øµ i Ø ¾Ë ¾

Equivalently, depth , is the smallest such that i .

Here is an inductive proof of a simple fact relating the number of constants in a term to its size.

3.2.8 Lemma: The number of distinct constants in a term Ø is always smaller than

j ´Øµj  ´Øµ ¾ the size of Ø ( Consts size ).

Proof: The property in itself is entirely obvious, of course. What’s interesting is the form of the inductive proof, which we’ll see repeated many times as we go along.

The proof proceeds by induction on the size of Ø. That is, assuming the desired Ø property for all terms smaller than Ø, we must prove it for itself; if we can do

this, we may conclude that the property holds for all Ø. There are three cases to consider:

Case: Ø is a constant

´Øµj = jfØgj = ½ = ´Øµ

Immediate: jConsts size .

Ø = ×Ùcc Ø ÔÖed Ø i×ÞeÖÓ Ø

½ ½

Case: ½ , ,or

j ´Ø µj  ´Ø µ ½

By the induction hypothesis, Consts ½ size . We now calculate as follows:

j ´Øµj = j ´Ø µj  ´Ø µ < ´Øµ ½ Consts Consts ½ size size .

January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 25

Ø = if Ø ØheÒ Ø eÐ×e Ø

¾ ¿

Case: ½

j ´Ø µj  ´Ø µ j ´Ø µj  ´Ø µ

½ ¾ ¾

By the induction hypothesis, Consts ½ size and Consts size and

j ´Ø µj  ´Ø µ j ´Øµj = j ´Ø µ [

¿ ½

Consts ¿ size . We now calculate as follows: Consts Consts

´Ø µ [ ´Ø µj  j ´Ø µj · j ´Ø µj · j ´Ø µj  ´Ø µ·

¿ ½ ¾ ¿ ½

Consts ¾ Consts Consts Consts Consts size

´Ø µ· ´Ø µ < ´Øµ ¾ ¿ size ¾ size size .

The form of this proof can be clarified by restating it as a general reasoning principle. (Compare this principle with the induction principle for natural num- bers on p. 18.)

3.2.9 Theorem [Principle of induction on terms]: Suppose that È is some predi-

´8Ö: ´Öµ < ´×µ È ´Öµµ

cate on terms. If we can show, for each ×, that size size implies

´×µ È ´Øµ Ø ¾ implies È , then we may conclude that holds for every term .

Proof: Exercise. ¾

Evaluation 3.2.10 Definition: The set of values is the subset of terms defined by the following abstract grammar:

Ú ::= (values...)

ØÖÙe value true

faÐ×e value false

¼ zero value Ú

×Ùcc successor value ! 3.2.11 Definition: The one-step evaluation relation is the smallest relation

containing all instances of the following rules:

if ØÖÙe ØheÒ Ø eÐ×e Ø ! Ø

¿ ¾

¾ (E-BOOLBETAT)

if faÐ×e ØheÒ Ø eÐ×e Ø ! Ø

¿ ¿

¾ (E-BOOLBETAF)

¼

Ø ! Ø ½

½ (E-IF)

¼

ØheÒ Ø eÐ×e Ø if Ø ØheÒ Ø eÐ×e Ø ! if Ø

¾ ¿ ½ ¾ ¿

½

¼

Ø ! Ø ½

½ (E-SUCC)

¼

×Ùcc Ø ! ×Ùcc Ø

½

½

¼ ! ¼

ÔÖed (E-BETANATPZ)

´×Ùcc Úµ ! Ú

ÔÖed (E-BETANATPS)

¼

Ø ! Ø ½

½ (E-PRED)

¼

ÔÖed Ø ! ÔÖed Ø

½ ½

January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 26

¼ ! ØÖÙe

i×ÞeÖÓ (E-BETANATIZ)

´×Ùcc Úµ ! faÐ×e

i×ÞeÖÓ (E-BETANATIS)

¼

Ø ! Ø ½

½ (E-ISZERO)

¼

i×ÞeÖÓ Ø ! i×ÞeÖÓ Ø

½

½

¾

£ ! 3.2.12 Definition: The multi-step evaluation relation is the reflexive, transi-

tive closure of one-step evaluation. That is, it is the smallest relation such that

¼ £ ¼

Ø ! Ø Ø ! Ø

¯ if then ,

£

Ø ! Ø Ø

¯ for all , and

£ ¼ ¼ £ ¼¼ £ ¼¼

Ø ! Ø Ø ! Ø Ø ! Ø ¾ ¯ if and , then .

3.2.13 Exercise [Quick check]: Rewrite the previous definition using a set of infer-

£ ¼

! Ø ¾ ence rules to define the relation Ø . (Solution on page 253.)

3.2.14 Definition: A term Ø is in normal form if no evaluation rule applies to it—

¼ ¼

Ø ! Ø ¾ i.e., if there is no Ø such that .

3.2.15 Definition: An evaluation sequence starting from a term Ø is a (finite or

Ø Ø ¾

infinite) sequence of terms ½ , ,...,such that

Ø ! Ø

½

Ø ! Ø

½ ¾

etc. ¾

3.2.16 Definition: A term is said to be stuck if it is a normal form but not a value. ¾

3.2.17 Exercise: Write an abstract grammar that generates all (and only) the stuck

arithmetic expressions. ¾

“Stuckness” gives us a simple notion of “run-time type error” for this rather abstract abstract machine. Intuitively, it characterizes the situations where the op- erational semantics does not know what to do because the program has reached a “meaningless state.” A more serious implementation might choose other behavior in these cases, such as dumping core. January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 27

3.3 Properties

3.3.1 Proposition: Every value is in normal form. ¾

Proof: By inspection of the definitions of values and one-step evaluation. ¾

¼ ¼¼

! Ø Ø ! Ø

3.3.2 Proposition [Determinacy of evaluation]: If Ø and , then

¼ ¼¼

= Ø ¾ Ø .

Proof: Exercise. (Solution on page 253.) ¾

£

Ø Ø ! Ú ¾

3.3.3 Definition: A value Ú is the result of a term if .

Û Ø

3.3.4 Proposition [Uniqueness of results]: If Ú and are both results of , then

= Û ¾ Ú .

Proof: Exercise. ¾

3.4 Implementation

Explanatory text still needs to be written. Note that this implementation is optimized for readability and for correspondence with the mathematical definitions, not for efficient execution! We’ll ignore parsing and printing, the top-level read-eval-print loop, etc. Interested readers are encouraged to have a look at the ML code for the whole typechecker.

Syntax

ØÝÔe iÒfÓ

ØÝÔe ØeÖÑ =

ÌÑÌÖÙe Óf iÒfÓ

| ÌÑFaÐ×e Óf iÒfÓ

| ÌÑÁf Óf iÒfÓ ¶ ØeÖÑ ¶ ØeÖÑ ¶ ØeÖÑ

| ÌÑZeÖÓ Óf iÒfÓ

| ÌÑËÙcc Óf iÒfÓ ¶ ØeÖÑ

| ÌÑÈÖed Óf iÒfÓ ¶ ØeÖÑ

| ÌÑÁ×ZeÖÓ Óf iÒfÓ ¶ ØeÖÑ

The iÒfÓ components of this datatype are extracted, as necessary, by the error printing functions. January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 28

Evaluation

eÜceÔØiÓÒ ÆÓ

ÐeØ Öec eÚaн Ø =

ÑaØch Ø ÛiØh

ÌÑÁf´fi¸Ø½¸Ø¾¸Ø¿µ ÛheÒ ÒÓØ ´i×ÚaРؽµ !

ÐeØ Ø½³ = eÚaн ؽ iÒ

ÌÑÁf´fi¸ ؽ³¸ ؾ¸ Ø¿µ

| ÌÑÁf´fi¸ÌÑÌÖÙe´_µ¸Ø¾¸Ø¿µ !

ؾ

| ÌÑÁf´fi¸ÌÑFaÐ×e´_µ¸Ø¾¸Ø¿µ !

Ø¿

| ÌÑËÙcc´fi¸Ø½µ ÛheÒ ÒÓØ ´i×ÚaРؽµ !

ÐeØ Ø½³ = eÚaн ؽ iÒ

ÌÑËÙcc´fi¸ ؽ³µ

| ÌÑÈÖed´fi¸Ø½µ ÛheÒ ÒÓØ ´i×ÚaРؽµ !

ÐeØ Ø½³ = eÚaн ؽ iÒ

ÌÑÈÖed´fi¸ ؽ³µ

| ÌÑÈÖed´_¸ÌÑZeÖÓ´_µµ !

ÌÑZeÖÓ´ÙÒkÒÓÛÒµ

| ÌÑÈÖed´_¸ÌÑËÙcc´_¸Ú½µµ !

Ú½

| ÌÑÁ×ZeÖÓ´fi¸Ø½µ ÛheÒ ÒÓØ ´i×ÚaРؽµ !

ÐeØ Ø½³ = eÚaн ؽ iÒ

ÌÑÁ×ZeÖÓ´fi¸ ؽ³µ

| ÌÑÁ×ZeÖÓ´_¸ÌÑZeÖÓ´_µµ !

ÌÑÌÖÙe´ÙÒkÒÓÛÒµ

| ÌÑÁ×ZeÖÓ´_¸ÌÑËÙcc´_¸_µµ !

ÌÑFaÐ×e´ÙÒkÒÓÛÒµ

| _ ! Öai×e ÆÓ

ÐeØ Öec eÚaÐ Ø =

ØÖÝ ÐeØ Ø³ = eÚaн Ø

iÒ eÚaРس

ÛiØh ÆÓ ! Ø

3.5 Summary January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 29

Booleans B (untyped)

Syntax

Ø ::= (terms...)

ØÖÙe constant true

faÐ×e constant false

Ø ØheÒ Ø eÐ×e Ø if conditional

Ú ::= (values...)

ØÖÙe value true

faÐ×e value false

¼

! Ø

Evaluation (Ø )

if ØÖÙe ØheÒ Ø eÐ×e Ø ! Ø

¿ ¾

¾ (E-BOOLBETAT)

if faÐ×e ØheÒ Ø eÐ×e Ø ! Ø

¿ ¿

¾ (E-BOOLBETAF)

¼

Ø ! Ø ½

½ (E-IF)

¼

if Ø ØheÒ Ø eÐ×e Ø ! if Ø ØheÒ Ø eÐ×e Ø

½ ¾ ¿ ¾ ¿

½ Æ Arithmetic expressions B (untyped)

New syntactic forms

Ø ::= ... (terms...)

¼ constant zero Ø

×Ùcc successor Ø

ÔÖed predecessor Ø i×ÞeÖÓ zero test

Ú ::= ... (values...)

¼ zero value Ú

×Ùcc successor value

¼

! Ø

New evaluation rules (Ø )

¼

Ø ! Ø ½

½ (E-SUCC)

¼

×Ùcc Ø ! ×Ùcc Ø

½

½

¼ ! ¼

ÔÖed (E-BETANATPZ)

´×Ùcc Úµ ! Ú

ÔÖed (E-BETANATPS)

¼

Ø ! Ø ½

½ (E-PRED)

¼

ÔÖed Ø ! ÔÖed Ø

½ ½

January 15, 2000 3. UNTYPED ARITHMETIC EXPRESSIONS 30

¼ ! ØÖÙe

i×ÞeÖÓ (E-BETANATIZ)

´×Ùcc Úµ ! faÐ×e

i×ÞeÖÓ (E-BETANATIS)

¼

Ø ! Ø ½

½ (E-ISZERO)

¼

i×ÞeÖÓ Ø ! i×ÞeÖÓ Ø

½ ½

3.6 Further Reading Chapter 4

The Untyped Lambda-Calculus

There may, indeed, be other applications of the system than its use as a logic. — Alonzo Church, 1932

In the mid 1960s, Peter Landin observed that a complex programming lan- guage can often be understood very cleanly by formulating it as a tiny “core cal- culus” capturing its essential mechanisms, together with a collection of conve- nient “derived forms” whose behavior is understood by translating them into the core [Lan64, Lan65, Lan66] (also cf. [Ten81]). The core language used by Landin was the lambda-calculus, a in which all computation is reduced to the basic operations of function definition and application. Since the 60s, the lambda-calculus has seen widespread use in the specification of programming lan- guage features, language design and implementation, and the study of type sys- tems. Its importance arises from the fact that it can be viewed simultaneously as a simple programming language in which computations can be described and as a mathematical object about which rigorous statements can be proved. The lambda-calculus is just one of a large number of core calculi that have been used for these purposes. For example, the pi-calculus of Robin Milner, Joachim Parrow, and David Walker [MPW92, Mil91] has become a popular core language for defining the semantics of message-based concurrent languages, while Mart´ın Abadi and ’s object calculus [AC96] distills the core features of many object-oriented languages. The concepts and techniques we will develop for the lambda-calculus can, in most cases, be transferred quite directly to other calculi. The lambda-calculus can be enriched in a variety of ways. First, it is often con- venient to add special concrete syntax for features like tuples and records whose behavior can already be simulated in the core language. More interestingly, we may want to provide more complex features such as mutable reference cells or nonlocal , which can be modeled in the core language only via rather heavy translations. Such extensions make the calculus look more like a full-

31 January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 32 blown high-level programming language in its own right, and lead eventually to languages such as ML [GMW79, MTH90, WAL · 89, MTHM97] and Scheme [SJ75, KCR98]. As we shall see, extensions to the core language often involve extensions to the type system as well. This chapter reviews the definition and some basic properties of the pure or untyped lambda-calculus.

4.1 Basics

Procedural abstraction is a key feature of most programming languages. Instead of writing the same calculation over and over, we write a procedure or function that performs the calculation abstractly, in terms of one or more named parameters; we then instantiate this function as needed, providing values for the parameters in each case. For example, it is second nature for a programmer to take a long and

repetitive expression like

´5¶4¶¿¶¾¶½µ · ´7¶6¶5¶4¶¿¶¾¶½µ ¹ ´¿¶¾¶½µ

and rewrite it as facØÓÖiaд5µ·facØÓÖiaд7µ¹fac ØÓÖi aд¿µ ¸

where:

facØÓÖiaдҵ = if Ò=¼ ØheÒ ½ eÐ×e Ò ¶ facØÓÖiaдҹ½µ facØÓÖiaÐ

For each nonnegative number Ò, instantiating the function with the ar-

Ò Òº ººº gument Ò yields a number, the factorial of , as result. Writing “ ”asa

shorthand for “the function that, for each Ò, yields...,” we can restate the definition

of facØÓÖiaÐ as:

facØÓÖiaÐ = Òº if Ò=¼ ØheÒ ½ eÐ×e Ò ¶ facØÓÖiaдҹ½µ

Òº if Ò=¼ ØheÒ ½ eÐ×e ººº

Then facØÓÖiaд¼µ means “the function ‘ ’ applied Ò

to the argument ¼,” that is, “the value that results when the bound variable

Òº if Ò=¼ ØheÒ ½ eÐ×e ººº ¼

in the function body ‘ ’ is replaced by ,” that is

¼=¼ ØheÒ ½ eÐ×e ººº ½ “if ,” that is, . In the 1930s, Alonzo Church invented a mathematical system called the lambda-

calculus (or -calculus) that embodies this kind of function definition and appli- cation in a pure form [Chu36, Chu41]. In the lambda-calculus everything is a func- tion: the arguments accepted by functions are themselves functions and the result returned by a function is another function. January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 33

Syntax

The syntax of the lambda-calculus comprises three kinds of terms. A variable Ü Ø

by itself is a lambda-term; the application of a lambda-term ½ to another lambda-

Ø Ø Ø Ü

½ ¾

term ¾ , written , is a lambda-term; and the abstraction of a variable from

Ø ܺ Ø ½ a lambda-term ½ , written , is a lambda-term. These forms are summarized in the following abstract grammar:

Ø ::= (terms...)

Ü variable ܺØ

 abstraction Ø

Ø application

Ø Ù

The letters ×, , and (with or without subscripts) are used throughout to stand

Ý Þ

for arbitrary lambda-terms, while Ü, , and are used to stand for arbitrary vari-

Ø Ù Ü Ý Þ able names. We call ×, , , , , and metavariables: they are “variables” in the sense that they stand for terms of the lambda-calculus, and “meta” in the sense that they are part of the metalanguage (i.e. English plus ordinary mathematical nota-

tions) in which an object language, the lambda-calculus, is being discussed. Since Ý the set of short names is limited, we will also sometimes use Ü, , etc. as object-

language variables, but the context of the discussion will always make it clear

ܺ ݺ Ü ´Ý ܵµ

which is which. For example, in a statement like “The term ´

Þº ×µ Þ = Ü × = ݺ Ü ´Ý ܵ Þ ×

has the form ´ , where and ,” the names and are Ý metavariables, whereas Ü and are object-language variables. A complete sum- mary of metavariable conventions appears in Appendix B. The words “lambda-term” (or just “term”) and “lambda-expression” are often used as synonyms. Note that what we’ve defined is only the abstract syntax of lambda-terms. In a full-scale programming language, we would also need to address concrete syntax issues of lexing, parsing, operator precedence, etc. For present purposes, though, it is better to avoid such issues by concentrating on the abstract syntax, using paren-

theses informally as necessary to clarify the tree structure of examples. Application

× Ù ´Ø ×µ Ù is taken to “associate to the left”—that is, Ø is considered the same as .

Also, the bodies of abstractions are assumed to extend as far to the right as possi-

Ѻ Òº Ñ Ò Ñ ܺ ´ݺ ´Ü ݵ ܵ

ble, so that writing  is the same as writing .

Ø ܺØ

The variable Ü is said to be bound in the body of the abstraction . Con-

× Ü

versely, we say that a variable Ü is free in a term if appears at some position in

Ü Ü

× where it is not bound by an enclosing abstraction on . For example, is free in

Ý ݺ Ü Ý ÜºÜ Þº ܺ ݺ Ü ´Ý Þµ Ü and , but not in or . A term with no free variables is said to be closed; closed terms are also some-

times called combinators. The simplest combinator is called the identity function:

id = ܺÜ; January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 34

Operational Semantics In its pure form, the lambda-calculus has no built-in constants or operators—no numbers, arithmetic operations, records, loops, sequencing, I/O, etc. The sole means by which terms “compute” is the application of functions to arguments,

which is captured in the following evaluation rule, traditionally called beta-reduction.

´ÜºØ µ Ú ! fÜ 7! Ú gØ

¾ ¾ ½¾

½¾ (E-BETA)

´ÜºØ µ Ú ¾ This rule says that an application of the form ½ (where the argument

has already been evaluated to a value), is evaluated by substituting the argument

Ú Ü Ø ´ܺܵ Ý Ý ½

¾ for the bound variable in the body . For example, evaluates to

ܺ Ü Ýµ ´Ù Öµ Ù Ö Ý ´ܺݺܵ Þ Û

and ´ evaluates to , while evaluates (by the

ݺ޵ Û Þ underlined redex) to ´ , which further evaluates to .

4.2 Programming in the Lambda-Calculus

The lambda-calculus is much more powerful than its tiny definition might suggest. For example, there is no built-in provision for multi-argument functions, but it is easy to achieve the same effect using higher-order functions that yield functions

as results.

Ü Ý

Suppose that × is a term involving two free variables and and we want ´Ô¸Õµ

to write a function f that, for each pair of arguments, yields the result of

Ü Õ Ý × f = ´Ü¸Ýµº×

substituting Ô for and for in . Instead of writing , as we might

= ܺÝº× f

in a higher-level programming language, we write f . That is, is a

Ü Õ Ý function that, given a value Ô for , yields a function that, given a value for ,

yields the desired result. We then apply f to its arguments one at a time, writing

Ô Õ ´ݺfÔ 7! Üg×µ Õ fÕ 7! ÝgfÔ 7! Üg× f , which reduces to and then to . This transformation of multi-argument functions into higher-order functions is often called after its popularizer, Haskell Curry. (It was actually invented by Sch¨onfinkel, but the term “Sch¨onfinkeling” has not caught on.)

Another common language feature that can easily be encoded in the lambda- fÐ× calculus is boolean values and conditionals. Define the terms ØÖÙ and as fol-

lows:

ØÖÙ = غ fº Ø;

fÐ× = غ fº f;

The only way to “interact” with combinators is by applying them to other

terms. For example, we can use application to define a combinator Øe×Ø with

b Ñ Ò Ñ b = ØÖÙ Õ

the property that Øe×Ø reduces to when and reduces to when

= fÐ×

b .

Øe×Ø = к Ѻ Òº Ð Ñ Ò;

January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 35

´Øe×Ø b Ñ Òµ

The Øe×Ø combinator does not actually do much: just reduces to

Ñ Òµ b

´b . In effect, the boolean value itself is the conditional: it takes two argu- fÐ×

ments and chooses the first (if it is ØÖÙ) or the second (if it is ). For example, the

ØÖÙ Ñ Òµ

term ´Øe×Ø reduces as follows:

Øe×Ø ØÖÙ Ñ Ò

´к Ѻ Òº Ð Ñ Òµ ØÖÙ Ñ Ò

= by definition

! ´Ѻ Òº ØÖÙ Ñ Òµ Ñ Ò

reducing the underlined redex

! ´Òº ØÖÙ Ñ Òµ Ò

reducing the underlined redex

! ØÖÙ Ñ Ò

reducing the underlined redex

´غfºØµ Ñ Ò

= by definition

! ´fº ѵ Ò

reducing the underlined redex

! Ñ reducing the underlined redex

We can also write boolean operators like logical conjunction as functions:

aÒd = bº cº b c fÐ×;

b c c b

That is, aÒd is a function that, given two boolean arguments and , returns if

fÐ× b fÐ× aÒd b c ØÖÙ b c ØÖÙ fÐ×

is ØÖÙ or if is ; thus yields if both and are and if

c fÐ×

either b or is .

aÒd ØÖÙ ØÖÙ;

Á

´غ fº ص

aÒd ØÖÙ fÐ×;

Á

´غ fº fµ

aÒd fÐ× ØÖÙ;

Á

´غ fº fµ

aÒd fÐ× fÐ×;

Á

´غ fº fµ

ÒÓØ ¾ 4.2.1 Exercise: Define logical ÓÖ and functions.

Using booleans, we can encode pairs of values as lambda-terms. Define:

ÔaiÖ = fº׺bº b f ×;

f×Ø = Ôº Ô ØÖÙ;

×Òd = Ôº Ô fÐ×;

Ñ Ò b b Ñ

That is, ÔaiÖ is a function that, when applied to a boolean , applies to

Ñ b ØÖÙ Ò b

and Ò. By the definition of booleans, this application yields if is and if is

f×Ø ×Òd fÐ×, so the first and second projection functions and can be implemented

January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 36

£

´ÔaiÖ Ñ Òµ ! simply by supplying the appropriate boolean. To check that f×Ø

Ñ, calculate as follows:

f×Ø ´ÔaiÖ Ñ Òµ

f×Ø ´´fº ׺ bº b f ×µ Ñ Òµ

= by definition

! f×Ø ´´׺ bº b Ñ ×µ Òµ

reducing the underlined redex

! f×Ø ´bº b Ñ Òµ

reducing the underlined redex

´Ôº Ô ØÖÙµ ´bº b Ñ Òµ

= by definition

! ´bº b Ñ Òµ ØÖÙ

reducing the underlined redex

! ØÖÙ Ñ Ò

reducing the underlined redex

£

! Ñ as before.

The encoding of numbers as lambda-terms is only slightly more intricate than

c c c

½ ¾

what we have just seen. Define the Church numerals ¼ , , , etc., as follows:

c = ׺ Þº Þ;

¼

c = ׺ Þº × Þ;

½

c = ׺ Þº × ´× Þµ;

¾

c = ׺ Þº × ´× ´× Þµµ;

¿

c = ׺ Þº × ´× ´× ´× Þµµµ;

4

eØcº

Ò c

That is, each number is represented by a combinator Ò that takes two argu-

× × Ò Þ ments, Þ and (for “zero” and “successor”), and applies , times, to . As with

booleans and pairs, this encoding makes numbers into active entities: the number Ò Ò is represented by a function that does something times—a kind of active unary numeral. We can define some common arithmetic operations on Church numerals as fol-

lows:

ÔÐÙ× = Ѻ Òº ׺ Þº Ñ × ´Ò × Þµ;

ØiÑe× = Ѻ Òº Ñ ´ÔÐÙ× Òµ c ;

¼

Ñ Ò Here, ÔÐÙ× is a combinator that takes two Church numerals, and , as arguments,

and yields another Church numeral—i.e., a function that accepts arguments Þ and

× Ò Þ × Þ Ò

×, applies iterated times to (by passing and as arguments to ), and then Ñ

applies × iterated more times to the result.

£

´ÔÐÙ× c c µ ! c ¾

½ ¿

4.2.2 Exercise: Verify that ¾ . ÔÐÙ×

The definition of ØiÑe× uses another trick: since takes its arguments one at a Ò

time, applying it to just one argument Ò yields the function that adds to whatever

Ñ c argument it is given. Passing this function as the second argument to and ¼ as

the first argument means “apply the function that adds Ò to its argument, iterated

Ñ Ò Ñ times, to zero,” i.e., “add together copies of .” 4.2.3 Exercise [Recommended]: Define a similar term for calculating the successor

of a number. (Solution on page 254.) ¾ January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 37

4.2.4 Exercise: Define a similar term for raising one number to the power of an-

other. ¾

To test whether a Church numeral is zero, we must apply it to a pair of terms

×× ×× ÞÞ fÐ×

ÞÞ and such that applying to one or more times yields , while not

ÞÞ ØÖÙ ×× applying it at all yields ØÖÙ. Clearly, we should take to be just . For ,we

use a function that throws away its argument and always returns fÐ×.

i×ÞÖÓ = Ѻ Ñ ´ܺ fÐ×µ ØÖÙ;

Surprisingly, it is quite a bit more difficult to subtract using Church numerals. It

can be done using the following rather tricky “predecessor function,” which, given

c c c c

¼ i·½ i

¼ as argument, returns and, given , returns :

ÞÞ = ÔaiÖ c c ;

¼ ¼

×× = Ôº ÔaiÖ ´×Òd Ôµ ´ÔÐÙ× c ´×Òd Ôµµ;

½

ÔÖd = Ѻ f×Ø ´Ñ ×× ÞÞµ; Ñ

This definition works by using Ñ as a function to apply copies of the function

×× ÞÞ ×× ÔaiÖ c c j

to the starting value . Each copy of takes a pair of numerals i

´ÔaiÖ c c µ ×× Ñ

j·½

as its argument and yields j as its result. So applying times to

´ÔaiÖ c c µ ´ÔaiÖ c c µ Ñ = ¼ ´ÔaiÖ c c µ Ñ

¼ ¼ ¼ ѹ½ Ñ ¼ yields when and when is

positive. In both cases, the predecessor of Ñ is found in the first component.

4.2.5 Exercise:

1. Use ÔÖd to define a subtraction function.

2. How many steps of evaluation (as a function of Ò) are required to calculate

´ÔÖd c µ ¾

the result of Ò ?

4.2.6 Exercise: Write a function eÕÙaÐ that tests two numbers for equality and re-

turns a boolean. For example,

eÕÙaÐ c c ;

¿ ¿

Á

´غ fº ص

eÕÙaÐ c c ;

¿ ¾

Á

´غ fº fµ

(Solution on page 254.) ¾

Other common datatypes like lists, trees, arrays, and variant records can be en- coded using similar techniques. Of course, in most programming languages based on the lambda-calculus, such basic data types are added as primitive constants, rather than being encoded. January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 38

4.2.7 Exercise [Recommended]: Build an encoding of lists in the pure lambda- cÓÒ×

calculus by defining a constant ÒiÐ (the empty list) and operations (for con- ØaiÐ structing a list from a new head element and an old list), head and (for ex-

tracting the parts of a list), and i×ÒÙÐÐ (for testing whether a list is empty).

One straightforward way to do this is to generalize the encoding of numbers as ØØ follows. A list is represented by a function that takes two arguments, hh and .If

the list is empty, this function simply returns ØØ. On the other hand, if the list has

Ø hh h ´Ø hh Øص head h and tail , the function calls , passing it and as parameters.

(In other words, a list is represented by its own fÓÐd function.)

Can you think of any different ways of encoding lists? (Solution on page 254.) ¾ Recall that a term that cannot take a step under the evaluation relation is said to be in normal form. Interestingly, in the untyped lambda-calculus, not every term

can be evaluated to a normal form. For example, the divergent combinator

ÓÑega = ´ܺ Ü Üµ ´ܺ Ü Üµ; can never be reduced to a value. It contains just one redex, and reducing this redex

yields exactly ÓÑega again! Terms with no normal form are sometimes said to diverge.

The ÓÑega combinator has a useful generalization called the fixed-point com-

binator (or Y -combinator), which can be used to define recursive functions such

as facØÓÖiaÐ.

fiÜÔÓiÒØ = fº ´ܺ f ´ݺ ´Ü ܵ ݵµ

´ܺ f ´ݺ ´Ü ܵ ݵµ;

fiÜÔÓiÒØ ff

The crucial property of fiÜÔÓiÒØ is that has the same behavior as

´fiÜÔÓiÒØ ffµ ff ff for any term . (Note that this is a call-by-value fixed point combinator, since we using a call-

by-value reduction strategy. The simpler call-by-name fixed point combinator

fiÜÔÓiÒØ = fº ´ܺ f ´Ü ܵµ

Ò

´ܺ f ´Ü ܵµ;

fiÜÔÓiÒØ ff is useless in a call-by-value setting, since an expression like Ò always

diverges, no matter what ff is.)

Now, suppose we want to write a recursive function definition of the form

= h ffi ff body containing —i.e., we want to write a definition where the term on

the right-hand side of the = uses the very function that we are defining, as in the

definition of facØÓÖiaÐ on page 32. The intention is that the recursive definition should be “unrolled” at the point where it occurs; for example, the definition of

facØÓÖiaÐ would intuitively be:

if Ò=¼ ØheÒ ½

eÐ×e Ò ¶ ´if Ò¹½=¼ ØheÒ ½

eÐ×e ´Ò¹½µ ¶ ´if ´Ò¹¾µ=¼ ØheÒ ½

eÐ×e ´Ò¹¾µ ¶ ºººµµ

January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 39

gg = fºh fi

This effect can be achieved using fiÜÔÓiÒØ by defining body containing

= fiÜÔÓiÒØ gg

and ff . For example, we can define the factorial function by

ff = fº Òº

Øe×Ø

´i×ÞÖÓ Òµ ´ܺ c µ ´ܺ ´ØiÑe× Ò ´f ´ÔÖd Òµµµµ c ;

½ ¼

facØÓÖiaÐ = fiÜÔÓiÒØ ff;

We then have:

eÕÙaÐ ´facØÓÖiaÐ c µ c ;

¿ 6

Á

´غ fº ص

4.2.8 Exercise [Recommended]: Use the fiÜÔÓiÒØ combinator and the encoding of lists from Exercise 4.2.7 to write a function that sums lists of church numerals.

(Solution on page 254.) ¾

4.3 Is the Lambda-Calculus a Programming Language? 4.4 Formalities

As we did in Chapter 3, we must now consider the syntax and operational seman- tics of the lambda-calculus in a little more detail. Most of the structure we need is closely analogous to what we saw there. However, the operation of substituting a term for a variable involves some surprising subtleties.

Syntax As in Chapter 3, the abstract grammar defining terms should be read as shorthand for the union of an inductively defined family of sets of abstract syntax trees. To

define it precisely, we begin with some set Î of variable names.

4.4.1 Definition [Terms]: The set of terms is the smallest set Ì such that

¾Ì Ü ¾Î

1. Ü for every ;

Ø ¾Ì Ü ÜºØ ¾Ì ½

2. if ½ and is a variable name, then ;

Ø ¾Ì Ø ¾Ì ´Ø Ø µ ¾Ì ¾

¾ ½ ¾ 3. if ½ and , then .

The size of a term Ø can be defined exactly as we did for arithmetic expressions in Definition 3.2.7. More interestingly, we can give a simple inductive definition of the set of variables appearing “free” in a lambda-term.

January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 40

´Øµ 4.4.2 Definition: The set of free variables of a term Ø, written FV , is defined as

follows:

ܵ = fÜg

FV´

´ÜºØ µ = ´Ø µ ÒfÜg ½

FV ½ FV

´Ø Ø µ = ´Ø µ [ ´Ø µ ¾

¾ ½ ¾ FV ½ FV FV Here is an inductive proof of a simple fact relating the definitions of size and free variables, analogous to Lemma 3.2.8 in the previous chapter.

4.4.3 Lemma: The number of distinct free variables in a term Ø is always smaller

j ´Øµj  ´Øµ ¾ than the size of Ø (in symbols: FV size ).

Proof: By induction on the size of Ø. (That is, assuming the desired property for Ø all terms smaller than Ø, we must prove it for itself; if we can do this, we may

conclude that the property holds for all Ø.) There are three cases to consider:

= Ü

Case: Ø

´Øµj = jfÜgj = ½ = ´Øµ

Immediate: jFV size .

Ø = ܺØ

Case: ½

j ´Ø µj  ´Ø µ ½

By the induction hypothesis, FV ½ size . We now calculate as follows:

j ´Øµj = j ´Ø µ ÒfÜgj  j ´Ø µj  ´Ø µ < ´Øµ

½ ½

FV FV ½ FV size size .

Ø = Ø Ø ¾

Case: ½

j ´Ø µj  ´Ø µ j ´Ø µj  ´Ø µ

½ ¾ ¾

By the induction hypothesis, FV ½ size and FV size . We now

j ´Øµj = j ´Ø µ [ ´Ø µj  j ´Ø µj · j ´Ø µj  ´Ø µ·

¾ ½ ¾ ½

calculate as follows: FV FV ½ FV FV FV size

´Ø µ < ´Øµ ¾ size ¾ size .

Substitution Dealing carefully with the operation of substitution requires some work. We’ll take it in two large steps. First (in this section), we’ll discuss the basic issues, iden- tify some traps for the unwary, and come up with a definition of substitution that is precise enough for most purposes. In Section 5.1 we’ll go the rest of the way, defining a more refined “nameless” presentation of terms on which substitution is completely formal (and, in particular, suitable for implementation). The reason for presenting both is that the nameless formulation becomes too fiddly to use all the time. Having worked it out in detail, we will return to the more comfortable, slightly informal presentation developed in this section, regarding it as a conve- nient shorthand for the other. It is instructive to arrive at the correct definition of substitution via a couple of

wrong attempts. First off, let’s try the most naive possible recursive definition:

fÜ 7! ×gÜ = ×

Ü 7! ×gÝ = Ý Ü 6= Ý

f if

fÜ 7! ×g´ÝºØ µ = ݺ fÜ 7! ×gØ

½ ½

fÜ 7! ×g´Ø Ø µ = fÜ 7! ×gØ fÜ 7! ×gØ

½ ¾ ½ ¾ January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 41

This definition works fine for most examples. For instance, it gives

fÜ 7! ´Þº Þ Ûµg´ݺ ܵ = ´ݺÞº Þ Ûµ; which is fine. However, if we are unlucky with our choice of bound variable

names, the definition breaks down. For example:

fÜ 7! Ýg´ܺܵ = ÜºÝ This conflicts with the basic intuition about functional abstractions that the alpha-

betic names of bound variables do not matter—the identity function is exactly the same

ÜºÜ ÝºÝ fÖaÒÞºfÖaÒÞ whether we write it  or or . If these do not behave exactly the same under substitution, then they will not behave the same under reduction either, which seems wrong. Clearly, the first mistake that we’ve made in the naive definition of substitution

is that we have not distinguished between free occurrences of a variable Ü in a

term Ø (which should get replaced during substitution) and bound ones, which Ø should not. When we reach an abstraction binding the name Ü inside of , the substitution operation should stop. This leads to the next attempt at a definition of

substitution:

fÜ 7! ×gÜ = ×

Ü 7! ×gÝ = Ý Ý 6= Ü

f if

¬

ݺ Ø Ý = Ü

½ if

fÜ 7! ×g´ÝºØ µ =

½

ݺ fÜ 7! ×gØ Ý 6= Ü

½ if

fÜ 7! ×g´Ø Ø µ = fÜ 7! ×gØ fÜ 7! ×gØ

½ ¾ ½ ¾

This is better, but it is still not quite right. For example, consider what happens

Ü ÞºÜ

when we substitute the term Þ for the variable in the term :

fÜ 7! Þg´޺ܵ = ÞºÞ

This time, we have made essentially the opposite mistake as in the previous un- ÞºÜ fortunate example: we’ve turned the constant function  into the identity func-

tion! Again, this occurred only because we happened to choose Þ as the name of

the bound variable in the constant function, so something is clearly still wrong. × This phenomenon of free variables in a term × becoming bound when is

naively substituted into a term Ø containing variable binders is called variable

capture. To avoid it, we need to make sure that the bound variable names of Ø

kept distinct from the free variable names of ×. A substitution operation that does this correctly is called capture-avoiding substitution. This is almost always what is meant by the unqualified term “substitution.” We can achieve this by adding

another side condition to the second clause of the abstraction case:

fÜ 7! ×gÜ = ×

fÜ 7! ×gÝ = Ý 6= Ü

if Ý

¬

ݺ Ø Ý = Ü

½ if

fÜ 7! ×g´ÝºØ µ =

½

ݺ fÜ 7! ×gØ Ý 6= Ü Ý ¾= ´×µ

½ if and FV

fÜ 7! ×g´Ø Ø µ = fÜ 7! ×gØ fÜ 7! ×gØ

½ ¾ ½ ¾ January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 42

We are almost there: this definition of substitution does the right thing when it does anything at all. The problem now is that our last fix has changed substitution

into a partial operation. For example, the new definition does not give any result

Ü 7! Ý Þg´ݺ Ü Ýµ Ý

at all for f : the bound variable of the term being substituted

´Ý Þµ into is not equal to Ü, but it does appear free in , so none of the clauses of the definition apply. One common fix for this last problem in the type systems and lambda-calculus literature is to work with terms “up to renaming of bound variables” (or “up to alpha-conversion”):

4.4.4 Convention: Terms that differ only in the names of bound variables are in-

terchangeable in all contexts. ¾

What this means in practice is that the name of any bound variable can be

changed to another name (consistently making the same change in the body), at

Ü 7!

any point where this is convenient. For example, if we want to calculate f

´ݺ Ü Ýµ ´Ûº Ü Ûµ Þg´ݺ Ü Ýµ

Ý , we first rewrite as, say, . We then calculate

Ü 7! Ý Þg´Ûº Ü Ûµ ´Ûº Ý Þ Ûµ f , giving . This renders the substitution operation “as good as total,” since whenever we find ourselves about to apply it to a collec- tion of arguments for which it is undefined, we can perform one or more steps of renaming as necessary, so that the side conditions are satisfied. Indeed, having adopted this convention, we can formulate the definition of substitution a little more tersely. The first clause for abstractions can be dropped,

since we can always assume (renaming if necessary) that the bound variable Ý is × different from both Ü and the free variables of . This yields the final form of the definition.

4.4.5 Definition [Substitution]:

fÜ 7! ×gÜ = ×

Ü 7! ×gÝ = Ý Ý 6= Ü

f if

fÜ 7! ×g´ÝºØ µ = ݺ fÜ 7! ×gØ Ý 6= Ü Ý ¾= ´×µ ½

½ if and FV

fÜ 7! ×g´Ø Ø µ = fÜ 7! ×gØ fÜ 7! ×gØ ¾

½ ¾ ½ ¾

The convention about implicit renaming of bound variables is is easy to work with, and its slight informality does not usually lead to trouble in practice. We shall adopt it in most of what follows. However, it is also important to know how to formulate basic operations such as substitution with complete rigor, so that we have a solid foundation to fall back on in case there is ever any question. We will see one way to accomplish this in Section 5.1.

4.4.6 Exercise: Without looking forward to Section 5.1, can you think of any other ways in which the incomplete definition of substitution might be repaired to give a complete operation, without resorting to a convention about implicit renaming

of bound variables? ¾ January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 43

Operational Semantics 4.4.7 Definition: The set of values is the subset of terms defined by the following abstract grammar:

Ú ::= (values...)

ܺØ

 abstraction value

¾ ! 4.4.8 Definition: The one-step evaluation relation is the smallest relation con-

taining all instances of the following rules:

´ÜºØ µ Ú ! fÜ 7! Ú gØ

¾ ¾ ½¾

½¾ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾ ¾

Summary

The foregoing definitions may be summarized compactly as follows. !  : Untyped lambda-calculus (untyped)

Syntax

Ø ::= (terms...)

Ü variable ܺØ

 abstraction Ø Ø application

Ú ::= (values...) ܺØ

 abstraction value

¼

! Ø

Evaluation (Ø )

´ÜºØ µ Ú ! fÜ 7! Ú gØ

¾ ¾ ½¾

½¾ (E-BETA)

¼

Ø ! Ø ½

½ (E-APP1)

¼

Ø Ø Ø ! Ø

¾ ½ ¾

½

¼

Ø ! Ø ¾

¾ (E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½ ¾ January 15, 2000 4. THE UNTYPED LAMBDA-CALCULUS 44

4.5 Further Reading

Information on the untyped lambda-calculus can be found in many places. The first and best is Barendregt’s encyclopedic monograph, The Lambda Calculus [Bar84]. Hindley and Seldin’s book [HS86] gives a more accessible treatment of some of the basic material. Barendregt’s article in the Handbook of Theoretical Computer Sci- ence [Bar90] is a compact survey. Material on lambda-calculus can also be found in many textbooks on functional programming languages (e.g. [AS85, FWH92, PJL92]) and programming language semantics (e.g.[Sch86, Gun92, Win93, Mit96]). Chapter 5

Implementing the Lambda-Calculus

Just because you’ve implemented something doesn’t mean you understand it. — Brian Cantwell Smith

5.1 Nameless Representation of Terms

In the previous chapter, we worked with terms “up to renaming of bound vari- ables.” This is fine for discussing basic concepts and for presenting proofs cleanly, but for building an implementation we need to choose a single concrete represen- tation for each term. There are various ways to do this: 1. We can represent a variable occurrence as a string. This makes our concrete (“algorithmic”) representation close to the declarative one, but it means that we have to alpha-convert during substitution. This becomes quite tricky and it is easy to introduce subtle bugs. 2. We can replace the names chosen by the programmer with some canonical naming scheme. 3. We can avoid substitution altogether by introducing mechanisms like clo- sures. We choose the second, using a well-known technique due to Nicolas de Bruijn [dB72]. Making this choice will require some work now, but will save us a lot of trouble- some when we come to implementing more complex systems.

45 January 15, 2000 5. IMPLEMENTING THE LAMBDA-CALCULUS 46

Syntax De Bruijn’s idea was that we can represent terms more straightforwardly—though less readibly—by making variable occurrences point directly to their binders, rather than referring to them by name. This can be accomplished by replacing named

variables by natural numbers, where the number k stands for “the variable bound

 ¼ ܺÜ

by the k’th enclosing ” (starting from ). For example, the ordinary term

º¼ ܺݺ Ü ´Ý ܵ

corresponds to the nameless term  , while is represented by

ºº ½ ´¼ ½µ the nameless term  . Nameless terms are also sometimes called de Bruijn terms, and the numeric variables in them are called de Bruijn indices. (In passing, a note on pronunciation: the closest English approximation to the second syllable in “de Bruijn” is “brown,” not “broyn.”)

5.1.1 Exercise [Quick check]: For each of the following combinators

c = Þº ׺ Þ;

¼

c = Þº ׺ × ´× Þµ;

¾

ÔÐÙ× = Ѻ Òº Þº ׺ Ñ ´Ò Þ ×µ ×;

fiÜÔÓiÒØ = fº ´ܺ f ´Ü ܵµ ´ܺ f ´Ü ܵµ;

fÓÓ = ´ܺ ´ܺ ܵµ ´ܺ ܵ;

write down the corresponding nameless term. ¾

Note that each (closed) ordinary term has just one de Bruijn representation, and that two ordinary terms are equivalent modulo renaming of bound variables exactly when they have the same de Bruijn representation.

To deal with terms containing free variables, we need the idea of a naming

ܺ Ý Ü

context. For example, suppose we want to represent  as a nameless term. Ý We know what to do with Ü, but we cannot see the binder for , so it is not clear how far out it might be and so we do not know what number to assign to it. The solution is to choose, once and for all, an assignment (called a naming context) of de Bruijn indices to free variables, and use this assignment consistently when we need to choose numbers for free variables. For example, suppose that we choose

to work under the following naming context:

= Ü 7! 4

Ý 7! ¿

Þ 7! ¾

a 7! ½

b 7! ¼

´Ý Þµµ ´4 ´¿ ¾µµ ܺ Ý Ü

Then ´Ü would be represented as , while would be

º 4 ¼ ÛºaºÜ ºº6 represented as  and would be represented as .

Actually, all we need to know about is the order in which the variables appear. Instead of writing it in tabular form, as we did above, we will elide the numbers and write it as a sequence.

January 15, 2000 5. IMPLEMENTING THE LAMBDA-CALCULUS 47

Ü Ü Î Ò

5.1.2 Definition: Suppose ¼ through are variable names in . The naming

= Ü ; Ü ; :::Ü ; Ü Ü i

Ò¹½ ½ ¼ i context Ò assigns to each the de Bruijn index . Note

that the rightmost variable in the sequence is given the index ¼. (This matches the

way we count s—from right to left—when converting a named term to nameless

´ µ fÜ ; :::; Ü g Ò

form.) We will write dom for the set ¼ of variable names mentioned ¾ in . Formally, we define the syntax of nameless terms almost exactly like the syntax of ordinary terms (Definition 4.4.1). The only difference is that we need to keep careful track of how many free variables each term may contain. That is, we dis-

tinguish the sets of terms with no free variables (called the ¼-terms), terms with at

most one free variable (½-terms), and so on.

Ì fÌ ; Ì ; Ì ; :::g

½ ¾ 5.1.3 Definition [Terms]: Let be the smallest family of sets ¼ such

that

k ¾Ì ¼  k<Ò

1. Ò whenever ;

Ø ¾Ì Ò>¼ ºØ ¾Ì

Ò¹½

2. if Ò and , then ;

Ø ¾Ì Ø ¾Ì Ø Ø ¾Ì

Ò ¾ Ò ½ ¾ Ò

3. if ½ and , then .

Ì Ò ¾

The elements of each Ò are called -terms. Ì

Note that the elements of Ò are terms with at most free variables numbered

¼ Ò ¹ ½ Ì between and : a given element of Ò need not have free variables with all

these numbers, or indeed any free variables at all. If Ø is closed, for example, it will

Ì Ò be an element of Ò for every .

Also, note that, strictly speaking, it does not make sense to speak of “some

¾ Ì Ø Ø ”—we always need to specify how many free variables might have. In

practice, though, we will often have some fixed naming context in mind; we will

Ø ¾Ì Ø ¾Ì Ò then abuse the notation slightly and write to mean Ò , where is the

length of .

5.1.4 Exercise: Give an alternative construction of the sets of Ò-terms in the style

of 3.2.2, and show (as we did in Fact ??) that it is equivalent to the one above. ¾

5.1.5 Exercise [Recommended]:

1. Define a function removenames that takes a naming context and an ordinary

´Øµ  ´ µµ term Ø (with FV dom and yields the corresponding nameless term.

2. Define a function restorenames that takes a nameless term Ø and a naming

context and produces an ordinary term. (To do this, you will need to “make

up” names for the variables bound by abstractions in Ø. You may assume that

the set Î of variable names is ordered, so that it makes sense to say “choose

µ the smallest variable name that is not already in dom´ .”)

January 15, 2000 5. IMPLEMENTING THE LAMBDA-CALCULUS 48

´ ´Øµµ =

This pair of functions should have the property that removenames restorenames

Ø ´ ´Øµµ = Ø Ø

for any nameless term , and similarly restorenames removenames ,up ¾ to renaming of bound variables, for any ordinary term Ø.

Shifting and Substitution Before defining substitution on nameless terms, we need one auxiliary operation

on terms, called “shifting,” which renumbers the indices of the free variables in a

fÜ 7! ×g´ݺܵ term. When a substitution goes under a -abstraction (as in ), the context in which the substitution is taking place becomes one variable longer than

the original; we need to increment the indices of the free variables in × so that they

keep referring to the same names in the new context as they did before.

Ø c

5.1.6 Definition [Shifting]: The d-place shift of a term above cutoff , written

d

" ´Øµ

c , is defined as follows:

¬

k k

d if

" ´kµ =

c

k  c · d

k if

d d

" ´ºØ µ = º " ´Ø µ

½ ½

c

c·½

d d d

" ´Ø Ø µ = " ´Ø µ " ´Ø µ

½ ¾ ½ ¾

c c c

d d

" ´Øµ " ¾ ´Øµ We will write for ¼ .

5.1.7 Exercise [Quick check]:

¾

´ºº ½ ´¼ ¾µµ

1. What is " ?

¾

´º ¼ ½ ´º ¼ ½ ¾µµ ¾

2. What is " ?

d

Ø Ò " ´Øµ ´Ò·dµ ¾

5.1.8 Exercise: Show that if is an -term, then c is an -term.

j 7! ×gØ

Now we are ready to define the substitution operator f . At the end, we

= ¼ will be most interested in substituting for the last variable in the context (i.e., j ),

since that is the case we need in order to define the reduction relation. However,  to substitute for variable ¼ in a -abstraction, we need to be able to substitute for

variable number ½ in the body. Thus, the definition of substitution must work on

an arbitrary variable. j

5.1.9 Definition [Substitution]: The substitution of a term × for variable number

fj 7! ×gØ

in a term Ø, written , is defined as follows:

¬

k = j

× if

fj 7! ×gk =

k otherwise

½

fj 7! ×g´ºØ µ = º fj · ½ 7!" ´×µgØ

½ ½

fj 7! ×g´Ø Ø µ = fj 7! ×gØ fj 7! ×gØ ¾

½ ¾ ½ ¾ January 15, 2000 5. IMPLEMENTING THE LAMBDA-CALCULUS 49

5.1.10 Exercise [Quick check]: Convert the following substitution operations to

= a; b nameless form (assuming the global context is ) and calculate their re- sults using the above definition. Do the answers make sense with respect to the

original definition of substitution on ordinary terms in Section 4.4?

¯ fb 7! ag ´b ´ܺݺbµµ

¯ fb 7! ag ´b ´ܺݺbµµ

¯ fb 7! ´a ´Þºaµµg ´b ´ܺbµµ ¾

Ø Ò j  Ò fj 7! ×gØ

5.1.11 Exercise: Show that if × and are -terms and , then is an ¾ Ò-term.

5.1.12 Exercise [Quick check]: Take a sheet of paper and, without looking at the

definitions of substitution and shifting above, see if you can regenerate them. ¾

5.1.13 Exercise [Recommended]: The definition of substitution on nameless terms should agree with our informal definition of substitution on ordinary terms. What theorem would need to be proved to justify this correspondence rigorously? For

extra credit, prove it. (Solution on page 255.) ¾

Evaluation We can now define the evaluation relation on nameless terms. The beta-reduction rule is defined in terms of our new nameless substitution

operation. The only slightly subtle technical point is that reducing a redex “uses

´ÜºØ µ Ú fÜ 7! Ú gØ

¾ ¾ ½ up” the bound variable—when we reduce ½ to , the bound

variable Ü disappears in the process. Thus, we will need to renumber the variables

of the result of substitution to take into account the fact that Ü is no longer part Ú

of the context. Similarly, we need to shift the variables in ¾ up by one before

Ø Ø ½

substituting into ½ to take account of the fact that is defined in a larger context Ú

than ¾ .

¹½ ½

´ºØ µ Ú ! " ´f¼ 7!" ´Ú µgØ µ

¾ ¾ ½ ½ (E-BETA) The other rules are identical to what we had before.

5.2 A Concrete Realization January 15, 2000 5. IMPLEMENTING THE LAMBDA-CALCULUS 50

Syntax

ØÝÔe ØeÖÑ =

ÌÑÎaÖ Óf iÒfÓ ¶ iÒØ ¶ iÒØ

| ÌÑAb× Óf iÒfÓ ¶ ×ØÖiÒg ¶ ØeÖÑ

| ÌÑAÔÔ Óf iÒfÓ ¶ ØeÖÑ ¶ ØeÖÑ

ÐeØ ØÑÁÒfÓ = fÙÒcØiÓÒ

ÌÑÎaÖ´fi¸_¸_µ ! fi

| ÌÑAb×´fi¸_¸_µ ! fi

| ÌÑAÔÔ´fi¸ _¸ _µ ! fi

Shifting and Substitution

ÐeØ ØÑÑaÔ ÓÒÚaÖ =

ÐeØ Öec ÛaÐk c = fÙÒcØiÓÒ

ÌÑÎaÖ´fi¸Ü¸Òµ ! ÓÒÚaÖ fi c Ü Ò

| ÌÑAb×´fi¸Ü¸Ø½µ ! ÌÑAb×´fi¸ ܸ ÛaÐk ´c·½µ ؽµ

| ÌÑAÔÔ´fi¸Ø½¸Ø¾µ ! ÌÑAÔÔ´fi¸ ÛaÐk c ؽ¸ ÛaÐk c ؾµ

iÒ ÛaÐk

ÐeØ ØÑ×hifØi d c Ø =

ØÑÑaÔ

´fÙÒ fi c Ü Ò ! if Ü>=c ØheÒ ÌÑÎaÖ´fi¸Ü·d¸Ò·dµ eÐ×e ÌÑÎaÖ´fi¸Ü¸Ò·dµµ

c

Ø

ÐeØ ØÑ×hifØ Ø d = ØÑ×hifØi d ¼ Ø

ÐeØ ØÑ×Ùb×Øi × j Ø =

ØÑÑaÔ

´fÙÒ fi j Ü Ò ! if Ü=j ØheÒ ´ØÑ×hifØ × jµ eÐ×e ÌÑÎaÖ´fi¸Ü¸Òµµ

j

Ø

ÐeØ ØÑ×Ùb×Ø × Ø = ØÑ×Ùb×Øi × ¼ Ø

ÐeØ ØÑ×Ùb×Ø×ÒiÔ × Ø = ØÑ×hifØ ´ØÑ×Ùb×Ø ´ØÑ×hifØ × ½µ ص ´¹½µ January 15, 2000 5. IMPLEMENTING THE LAMBDA-CALCULUS 51

Evaluation

ÐeØ Öec i×ÚaÐ cØÜ = fÙÒcØiÓÒ

ÌÑAb×´_¸_¸_µ ! ØÖÙe

| _ ! faÐ×e

ÐeØ Öec eÚaÐ cØÜ Ø =

ØÖÝ ÐeØ Ø³ = eÚaн cØÜ Ø

iÒ eÚaÐ cØÜ Ø³

ÛiØh ÆÓ ! Ø

5.3 Ordinary vs. Nameless Representations

Strictly speaking, having gone to the trouble of making all this so precise, we should now continue through the rest of the material in the course using de Bruijn representations consistently throughout. However, we will not do this, as it would make the text essentially unreadable. Instead, we will adopt the following com- promise:

¯ In this chapter and in all the implementation sections to follow, we use de Bruijn representations faithfully.

¯ In textual (and TeXtual) presentations of calculi, discussions, examples, and proofs, we will stick with the original presentation in terms of named vari- ables. However, we will always regard this as a convenient shorthand for an

underlying de Bruijn representation. For example, when we write

´ÜºØ µ Ø ! fÜ 7! Ø gØ

½½ ¾ ¾ ½½

we will actually mean:

¹½ ½

´ºØ µ Ø !" ´f¼ 7!" ´Ø µgØ µ

½½ ¾ ¾ ½½

In particular, this convention has the following consequences: 1. we always work “up to alpha-conversion,” ignoring the particular names chosen for bound variables, and 2. whenever we mention a term, we will always (at least implicitly) have some context in mind that imposes a numerical ordering on its free vari- able names. Chapter 6

Typed Arithmetic Expressions

This and the following chapter are technically mostly complete but the text needs to be expanded. The idea is that, as we did in the untyped case, we go through all the basic facts about typed calculi in the very simple setting of just numbers and booleans, then redo it all for the lambda-calculus.

6.1 Syntax

6.1.1 Definition: The set of types for arithmetic expressions contains just the sym- ÆaØ bols BÓÓÐ and :

Ì ::= (types...)

BÓÓÐ type of booleans

ÆaØ type of natural numbers

Ì Í ¾ The metavariables Ë, , , etc. range over types.

6.2 The Typing Relation

The type system for arithmetic expressions is defined by a set of rules assigning

Ø : Ì Ø Ì

types to terms. We write “` ” to mean “term has type .” ÆaØ For example, the fact that the term ¼ has the type is captured by the follow-

ing axiom:

: ÆaØ

¼ (T-ZERO)

×Ùcc Ø ÆaØ Ø ÆaØ ½

Similarly, the term ½ has type as long as has type .

Ø : ÆaØ ½

(T-SUCC)

×Ùcc Ø : ÆaØ ½

52

January 15, 2000 6. TYPED ARITHMETIC EXPRESSIONS 53

ÆaØ ÆaØ

Likewise, ÔÖed yields a when its argument has type

Ø : ÆaØ ½

(T-PRED)

ÔÖed Ø : ÆaØ

½

BÓÓÐ ÆaØ

and i×ÞeÖÓ yields a when its argument has type :

Ø : ÆaØ ½

(T-ISZERO)

i×ÞeÖÓ Ø : BÓÓÐ ½

The boolean constants both have type BÓÓÐ

: BÓÓÐ

ØÖÙe (T-TRUE)

: BÓÓÐ faÐ×e (T-FALSE)

The only interesting typing rule is the one for if expressions:

Ø : BÓÓÐ Ø : Ì Ø : Ì

½ ¾ ¿

(T-IF)

if Ø ØheÒ Ø eÐ×e Ø : Ì

½ ¾ ¿ if

The metavariable Ì is used to indicate that the result of the is the type of the

eÐ×e ÆaØ BÓÓÐ ØheÒ- and - branches, and that this may be any type (either or or, when we get to calculi with more interesting sets of types, any other type whatso- ever).

6.3 Properties of Typing and Reduction

Typing Derivations

Formally, the typing relation can be thought of as a simple logic for proving typing

Ø : Ì

assertions (sometimes called typing judgements) of the form ` , pronounced Ì “the term Ø has the type .” The provable statements of this logic are defined as follows: 6.3.1 Definition: The typing relation is the least two-place relation containing all instances of the axioms T-ZERO,T-TRUE, and T-FALSE and closed under all in-

stances of the remaining rules. (In the literature on type systems, the symbol ¾ is ¾ often used instead of : for the typing relation.)

6.3.2 Definition: A typing derivation is a tree of instances of the typing rules.

Ø : Ì

Each statement ` in the typing relation is justified by a typing derivation

Ø : Ì D :: Â D

with conclusion ` . We sometimes write to indicate that is a deriva-

D :: Â D Â

tion tree with conclusion  . When for some , we say that is derivable. ¾

6.3.3 Theorem [Principle of induction on typing derivations]: Suppose that È is

some predicate on typing statements. If we can show, for each typing derivation

¼ ¼ ¼ ¼

:: Â ´È ´Â µ D :: Â ´D µ < ´D µµ È ´Â µ

D , that , for all with size size implies , then we

´Â µ ¾ may conclude that È holds for every derivable typing statement. January 15, 2000 6. TYPED ARITHMETIC EXPRESSIONS 54

Typechecking

6.3.4 Lemma [Inversion of the typing relation]:

¼ : Ê Ê = ÆaØ

1. If ` , then .

` ×Ùcc Ø : Ê Ê = ÆaØ ` Ø : ÆaØ ½

2. If ½ , then and .

` ÔÖed Ø : Ê Ê = ÆaØ ` Ø : ÆaØ ½

3. If ½ , then and .

` i×ÞeÖÓ Ø : Ê Ê = BÓÓÐ ` Ø : ÆaØ ½

4. If ½ , then and .

ØÖÙe : Ê Ê = BÓÓÐ

5. If ` , then .

faÐ×e : Ê Ê = BÓÓÐ

6. If ` , then .

` if Ø ØheÒ Ø eÐ×e Ø : Ê

¾ ¿

7. If ½ , then

` Ø : BÓÓÐ

½

` Ø : Ê

¾

` Ø : Ê: ¿ The inversion lemma is sometimes called the generation lemma for the typing re- lation, since, given a valid typing statement, it shows how proofs of this statement

might have been generated. ¾

Proof: Immediate from the definition of the typing relation. ¾

6.3.5 Theorem [Uniqueness of Types]: Each term Ø has at most one type. That is,

if Ø is typeable, then its type is unique. Moreover, there is just one derivation of

this typing built from the inference rules of Definition 6.3.1. ¾

Proof: Exercise. ¾

Safety = Preservation + Progress The most important property of this type system (or any other) is soundness: well- typed programs do not “go wrong.” A simple way of formalizing this fact is the observation that well-typed programs can only reduce to well-typed programs—

that is, a well-typed program can never reach an ill-typed state at run-time.

£

Ø : Ì Ø !

6.3.6 Theorem [Preservation of types during evaluation]: If ` and

¼ ¼

` Ø : Ì ¾ Ø , then .

Proof: Exercise. ¾ January 15, 2000 6. TYPED ARITHMETIC EXPRESSIONS 55

The preservation theorem is often called “subject reduction” (or “subject evalu-

Ø : Ì

ation”) in the literature—the intuition being that a typing statement ` can be

Ì Ø thought of as a sentence: “Ø has type .” The term is the subject of this sentence, and the subject reduction property then says that the truth of the sentence is stable under reduction of the subject. Recall (from Definition3.2.16) that a “stuck” term is one that is in normal form

but not a value.

¼

Ø : Ì Ø Ø

6.3.7 Theorem [Progress]: If ` , then either is a value or there is some

¼

! Ø ¾ such that Ø .

Proof: Exercise. ¾

The combination of the latter property with the preservation theorem guar- antees that “well-typed terms never get stuck.” This combination of properties captures what is usually thought of as “” or “type soundness.”

6.3.8 Exercise [Recommended]: Having seen the “subject reduction” property, we

may wonder whether the opposite (“subject expansion”) property also holds. Is it

£ ¼ ¼

! Ø ` Ø : Ì ` Ø : Ì always the case that, if Ø and , then ? If so, prove it. If not,

give a counterexample. (Solution on page 255.) ¾

6.4 Implementation

ØÝÔe ØÝ =

ÌÝBÓÓÐ

| ÌÝÆaØ

ÐeØ Öec ØÝeÕÚ ØÝË ØÝÌ =

ÑaØch ´ØÝ˸ØÝ̵ ÛiØh

´ÌÝBÓÓиÌÝBÓÓе ! ØÖÙe

| ´ÌÝÆaظÌÝÆaص ! ØÖÙe

| _ ! faÐ×e

ÚaÐ eÖÖÓÖ : iÒfÓ ! ×ØÖiÒg ! ³a

ÐeØ Öec ØÝÔeÓf Ø =

ÑaØch Ø ÛiØh

ÌÑÌÖÙe´fiµ !

ÌÝBÓÓÐ

| ÌÑFaÐ×e´fiµ !

ÌÝBÓÓÐ

| ÌÑÁf´fi¸×½¸×¾¸×¿µ !

if ØÝeÕÚ ´ØÝÔeÓf ×½µ ÌÝBÓÓÐ ØheÒ

ÐeØ ØÝË = ØÝÔeÓf ×¾ iÒ

January 15, 2000 6. TYPED ARITHMETIC EXPRESSIONS 56

if ØÝeÕÚ ØÝË ´ØÝÔeÓf ׿µ ØheÒ ØÝË

eÐ×e eÖÖÓÖ fi "aÖÑ× Óf cÓÒdiØiÓÒaÐ haÚe diffeÖeÒØ ØÝÔe×"

eÐ×e eÖÖÓÖ fi "gÙaÖd Óf cÓÒdiØiÓÒaÐ ÒÓØ a bÓÓÐeaÒ"

| ÌÑZeÖÓ´fiµ !

ÌÝÆaØ

| ÌÑËÙcc´fi¸Ø½µ !

if ØÝeÕÚ ´ØÝÔeÓf ؽµ ÌÝÆaØ ØheÒ ÌÝÆaØ

eÐ×e eÖÖÓÖ fi "aÖgÙÑeÒØ Óf ×Ùcc i× ÒÓØ a ÒÙÑbeÖ"

| ÌÑÈÖed´fi¸Ø½µ !

if ØÝeÕÚ ´ØÝÔeÓf ؽµ ÌÝÆaØ ØheÒ ÌÝÆaØ

eÐ×e eÖÖÓÖ fi "aÖgÙÑeÒØ Óf ÔÖed i× ÒÓØ a ÒÙÑbeÖ"

| ÌÑÁ×ZeÖÓ´fi¸Ø½µ !

if ØÝeÕÚ ´ØÝÔeÓf ؽµ ÌÝÆaØ ØheÒ ÌÝBÓÓÐ

eÐ×e eÖÖÓÖ fi "aÖgÙÑeÒØ Óf i×ÞeÖÓ i× ÒÓØ a ÒÙÑbeÖ"

6.5 Summary

Typing rules for booleans B (typed)

New syntactic forms

Ì ::= ... (types...)

BÓÓÐ type of booleans

: Ì

New typing rules (Ø )

: BÓÓÐ

ØÖÙe (T-TRUE)

: BÓÓÐ

faÐ×e (T-FALSE)

Ø : BÓÓÐ Ø : Ì Ø : Ì

¾ ¿

½ (T-IF)

if Ø ØheÒ Ø eÐ×e Ø : Ì

½ ¾ ¿ Æ Typing rules for numbers B (typed)

New syntactic forms

Ì ::= ... (types...)

ÆaØ type of natural numbers

: Ì

New typing rules (Ø )

: ÆaØ ¼ (T-ZERO)

January 15, 2000 6. TYPED ARITHMETIC EXPRESSIONS 57

Ø : ÆaØ

½ (T-SUCC)

×Ùcc Ø : ÆaØ

½

Ø : ÆaØ

½ (T-PRED)

ÔÖed Ø : ÆaØ

½

Ø : ÆaØ

½ (T-ISZERO)

i×ÞeÖÓ Ø : BÓÓÐ ½ Chapter 7

Simply Typed Lambda-Calculus

This chapter introduces the most elementary member of the family of typed lan- guages that we shall be studying for the rest of the course: the simply typed lambda-calculus of Church [Chu40] and Curry [CF58].

7.1 Syntax

7.1.1 Definition: The set of simple types over the atomic type BÓÓÐ (for brevity, we omit natural numbers) is generated by the following grammar:

Ì ::= (types...)

!Ì Ì type of functions

BÓÓÐ type of booleans

Ë!Ì!Í Ë!´Ì!͵ ¾ The ! is right-associative: stands for .

7.1.2 Definition: The abstract syntax of simply typed lambda-terms (with booleans and conditional) is defined by the following grammar:

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø Ø application

ØÖÙe constant true

faÐ×e constant false

Ø ØheÒ Ø eÐ×e Ø

if conditional ¾

58 January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 59

In the literature on type systems, two different presentation styles are com- monly used:

¯ In implicitly typed (or, for historical reasons, Curry-style) systems, the pure (untyped) lambda-calculus is used as the term language. The typing rules define a relation between untyped terms and the types that classify them.

¯ In explicitly typed (or Church-style) systems, the term language itself is re- fined so that terms carry some type information within them; for example, the bound variables in function abstractions are always annotated with the type of the expected parameter. The type system relates typed terms and their types.

To a large degree, the choice is a matter of taste, though explicitly typed systems generally pose fewer algorithmic problems for typecheckers. We will adopt an explicitly typed presentation throughout.

7.2 The Typing Relation

Ü:Ì ºØ ½

In order to assign a type to an abstraction like ¾ , we need to know what Ø

will happen later when it is applied to some argument ¾ . The annotation on the Ì

bound variable tells us that we may assume that the argument will be of type ¾ . Ø

In other words, the type of the result will be just the type of ½ , where occurrences

Ü Ø Ì ¾ of in ½ are assumed to denote terms of type . This intuition is captured by the

following rule:

Ü:Ì ` Ø : Ì

½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

Since, in general, function abstractions can be nested, typing assertions actually

` Ø : Ì Ø Ì have the form , pronounced “term has type under the assumptions

about the types of its free variables.” Formally, the typing context is just a list of

variables and their types, and the “comma” operator extends by concatenating a

new binding on the right. To avoid confusion between the new binding and any Ü

bindings that may already appear in , we require that the name be chosen so

µ that it does not already appear in dom´ . (As usual, this condition can always be

satisfied by renaming the bound variable if necessary.) can thus be thought of

as a finite function from variables to their types. Following this intuition, we will

µ ´Üµ Ì

write dom´ for the set of variables bound by and for the type associated with Ü in .

So the rule for typing abstractions actually has the general form

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾ where the premise adds one more assumption to those in the conclusion. January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 60

The typing rule for variables follows immediately from this discussion. A vari-

able has whatever type we are currently assuming it to have:

Ü:Ì ¾

(T-VAR)

` Ü : Ì

Next, we need a rule for application:

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

Ø Ì Ì

¾ ½ In English: If ½ evaluates to a function mapping arguments in to results in

(under the assumption that the terms represented by its free variables yield results

Ø Ì ¾

of the types associated to them by ), and if ¾ evaluates to a result in , then the

Ø Ø Ì

¾ ½ result of applying ½ to will be a value of type . We have now given typing rules for each of the individual constructs in our simple language. To assign types to whole programs, we combine these rules

into derivation trees. For example, here is a derivation tree showing that the term

Ü:BÓÓкܵ ØÖÙe BÓÓÐ ´ has type in the empty context:

T-VAR

Ü:BÓÓÐ ` Ü : BÓÓÐ

T-ABS T-TRUE

` Ü:BÓÓÐºÜ : BÓÓÐ!BÓÓÐ ` ØÖÙe : BÓÓÐ

T-APP

` ´Ü:BÓÓкܵ ØÖÙe : BÓÓÐ 7.2.1 Exercise [Quick check]: Show (by exhibiting derivation trees) that the fol-

lowing terms have the indicated types in the given contexts:

:BÓÓÐ!BÓÓÐ ` f ´if faÐ×e ØheÒ ØÖÙe eÐ×e faÐ×eµ : BÓÓÐ

1. f

:BÓÓÐ!BÓÓÐ ` Ü:BÓÓк f ´if Ü ØheÒ faÐ×e eÐ×e ܵ : BÓÓÐ!BÓÓÐ ¾

2. f

f Ü Ý

7.2.2 Exercise [Quick check]: Find a context under which the term has ¾ type BÓÓÐ. Can you give a simple description of the set of all such contexts?

It is interesting to note that, in the above discussion, the “!” type constructor comes with typing rules of two kinds: 1. an introduction rule describing how elements of the type can be created, and 2. an elimination rule describing how elements of the type can be used. This terminology, which arises from connections between type theory and logic, is frequently useful in discussing type systems. When we come to consider more complex systems later in the course, we’ll see a similar pattern of linked introduc- tion and elimination rules being repeated for each type constructor we consider.

7.2.3 Exercise [Quick check]: Which of the rules for the type BÓÓÐ are introduction

rules and which are elimination rules? (Solution on page 255.) ¾ January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 61

7.3 Summary

We have been discussing the simply typed lambda-calculus with booleans and

!B conditionals,  . In later chapters, we are going to want to extend the simply typed lambda-calculus with many other base types, in addition to or instead of

booleans. We therefore split the formal summary of the system into two pieces: the ! pure simply  , with no base types at all, and a separate

extension with booleans.

! !  : Simply typed lambda-calculus (typed)

Syntax

Ø ::= (terms...)

Ü variable

Ü :Ì ºØ

 abstraction Ø Ø application

Ú ::= (values...)

Ü :Ì ºØ  abstraction value

Ì ::= (types...)

!Ì Ì type of functions

::= (contexts...)

; empty context Ü:Ì

; term variable binding

¼

! Ø

Evaluation (Ø )

´Ü :Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

` Ø : Ì

Typing ( )

Ü:Ì ¾

(T-VAR)

` Ü : Ì

; Ü:Ì ` Ø : Ì

¾ ¾

½ (T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 62

` Ø : Ì !Ì ` Ø : Ì

½½ ½¾ ¾ ½½

½ (T-APP)

` Ø Ø : Ì

½ ¾ ½¾

The highlighted areas here are used to mark material that is new with respect to the untyped lambda-calculus—whole new rules as well as new that need to be

added to rules that we have already seen. ! 7.3.1 Exercise [Quick check]: The system  by itself is actually trivial, in the

sense that it has no well-typed programs at all. Why? (Solution on page 255.) ¾

7.4 Properties of Typing and Reduction

Typechecking As in Chapter 6, we need to develop a few basic lemmas before we can prove type soundness. Most of these are similar to what we saw before (just adding

contexts to the typing relation and adding appropriate clauses for -terms. The only significant new requirement is a substitution principle for the typing relation (Lemma 7.4.9).

7.4.1 Lemma [Inversion of the typing relation]:

` Ü : Ê Ü:Ê ¾

1. If , then .

` Ü:Ì º Ø : Ê !Ê Ê = Ì ; Ü:Ì ` Ø : Ê

½ ¾ ½ ¾ ¾ ¾ ½ ½

2. If ¾ , then and .

` Ø Ø : Ê Ì ` Ø : Ì !Ê

¾ ¾ ½ ¾

3. If ½ , then there is some type such that and

` Ø : Ì ¾

¾ .

` ØÖÙe : Ê Ê = BÓÓÐ

4. If , then .

` faÐ×e : Ê Ê = BÓÓÐ

5. If , then .

` if Ø ØheÒ Ø eÐ×e Ø : Ê

¾ ¿

6. If ½ , then

` Ø : BÓÓÐ

½

` Ø : Ê

¾

` Ø : Ê: ¾ ¿

Proof: Immediate from the definition of the typing relation. ¾ ! 7.4.2 Exercise [Easy]: Write out a typechecking algorithm for  in pseudo-code or a programming language of your choice. Compare your answer with the ML

implementation in Section 7.5. ¾ January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 63

In Section 7.1, we chose to use an explicitly typed presentation of the calculus, partly in order to simplify the algorithmic issues involved in typechecking. This involved adding type annotations to bound variables in function abstractions, but nowhere else. In what sense is this “enough”? One answer is provided by the “uniqueness of types” theorem, the substance of which is that well-typed terms are in one-to-one correspondence with the typing derivations that justify their well-typedness (in a given environment). The typing derivation can be recovered immediately from the term, and vice versa. In fact, the correspondence is so straightforward that, in a sense, there is little difference be- tween the term and the derivation. (For many of the type systems that we will see, this simple correspondence will not hold: there will be significant work involved

in showing that typing derivations can be recovered effectively from typed terms.) Ø 7.4.3 Theorem [Uniqueness of Types]: In a given typing context , a term (with

free variables all in the domain of ) has at most one type. That is, if a term is typeable, then its type is unique. Moreover, there is just one derivation of this

typing built from the inference rules that generate the typing relation. ¾ The proof of the uniqueness theorem is so direct that there is almost nothing to say. We present a few cases carefully just to illustrate the structure of proofs by

induction on typing derivations.

` Ø : Ë ` Ø : Ì

Proof: Suppose that and . We show, by induction on a deriva-

` Ø : Ì Ë = Ì

tion of , that .

= Ü

Case T-VAR: Ø

¾

with Ü:Ì

` Ø :

By case (1) of the inversion lemma (7.4.1), the final rule in any derivation of

Ë = Ì

Ë must also be T-VAR, and .

Ø = Ý:Ì ºØ ½

Case T-ABS: ¾

Ì = Ì !Ì

¾ ½

; Ý:Ì ` Ø : Ì

¾ ½ ½

` Ø : Ë By case (2) of the inversion lemma, the final rule in any derivation of

must also be T-ABS, and this derivation must have a subderivation with conclu-

; Ý:Ì ` Ø : Ë Ë = Ì !Ë

½ ½ ¾ ½

sion ¾ , with . By the induction hypothesis (on the

; Ý:Ì ` Ø : Ì Ë = Ì

½ ½ ½ ½

subderivation with conclusion ( ¾ ), we obtain , from which

= Ì Ë is immediate. Case T-APP,T-TRUE,T-FALSE,T-IF:

Similar. ¾

7.4.4 Exercise [Quick check]: Write out the case for T-APP. ¾

Ì `

7.4.5 Exercise [Recommended]: Is there any context and type such that

Ü Ü : Ì Ì ` Ü Ü : Ì ? If so, give and and show a typing derivation for ; if not,

prove it. ¾ January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 64

We shall sometimes need to talk about the types of subterms of well-typed terms. The following notation is useful for this purpose.

7.4.6 Definition: Suppose the term × is well typed with respect to the typing con-

Ö × ´Öµ Ê

text , and that is some subterm of . We write for the type such

¼ ¼

` Ö : Ê

that , where is calculated by extending with bindings corresponding Ö

to all of the function abstractions inside × under which occurs. For example, if

= f:A!Bº g:Aº f g Ö = f g ´Öµ=B

× and , then typeOf . When (as in this chap-

´Öµ

ter) is fixed for the whole discussion, we usually elide it, writing just typeOf . ¾ Note that Ê is unique, by Theorem 7.4.3. We close this section with a couple of “structural lemmas” for the typing re- lation. These are not particularly interesting in themselves, but will permit us to

perform some useful manipulations of typing derivations in later proofs.

` Ø : Ì ¡ ¡ ` Ø :

7.4.7 Lemma [Permutation]: If and is a permutation of , then ¾ Ì. Moreover, the latter derivation has the same depth as the former.

Proof: Straightforward induction on typing derivations. ¾

` Ø : Ì Ü ¾= ´ µ ; Ü:Ë ` Ø : Ì 7.4.8 Lemma [Weakening]: If and dom , then .

Moreover, the latter derivation has the same depth as the former. ¾

Proof: Straightforward induction on typing derivations. ¾

Typing and Substitution

Ü:Ë ` Ø : Ì ` × : Ë ` fÜ 7! ×gØ :

7.4.9 Lemma [Substitution]: If ; and , then ¾ Ì. 7.4.10 Exercise [Recommended]: Prove the substitution lemma, using an induc- tion on the depth of typing derivations and Lemma 7.4.1. The full proof appears in the solutions; try to write it out yourself before having a look at the answer.

(Solution on page 255.) ¾

Type Soundness

£

` Ø : Ì Ø !

7.4.11 Theorem [Preservation of types during evaluation]: If and

¼ ¼

` Ø : Ì ¾ Ø , then .

Proof: ¾

` Ø : Ì Ø 7.4.12 Theorem [Progress]: Suppose Ø is closed and stuck. If , then is a

value. ¾ ØÖÙe

Proof: Outline: first show that every closed value of type BÓÓÐ is either or

Ë!Ì  ¾ faÐ×e and every closed value of type is a abstraction. January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 65

7.5 Implementation

ØÝÔe ØÝ =

ÌÝAÖÖ Óf ØÝ ¶ ØÝ

| ÌÝBÓÓÐ

ØÝÔe ØeÖÑ =

ÌÑÎaÖ Óf iÒfÓ ¶ iÒØ ¶ iÒØ

| ÌÑAb× Óf iÒfÓ ¶ ×ØÖiÒg ¶ ØÝ ¶ ØeÖÑ

| ÌÑAÔÔ Óf iÒfÓ ¶ ØeÖÑ ¶ ØeÖÑ

| ÌÑÌÖÙe Óf iÒfÓ

| ÌÑFaÐ×e Óf iÒfÓ

| ÌÑÁf Óf iÒfÓ ¶ ØeÖÑ ¶ ØeÖÑ ¶ ØeÖÑ

ÐeØ Öec ØÝeÕÚ ØÝË ØÝÌ =

ÑaØch ´ØÝ˸ØÝ̵ ÛiØh

´ÌÝAÖÖ´ØÝ˽¸ØÝ˾µ¸ÌÝAÖÖ´ØÝ̽¸ ØÝ̾µ µ !

´ØÝeÕÚ ØÝ˽ ØÝ̽µ ²² ´ØÝeÕÚ ØÝ˾ ØÝ̾µ

| ´ÌÝBÓÓиÌÝBÓÓе ! ØÖÙe

| _ ! faÐ×e

ÐeØ Öec ØÝÔeÓf cØÜ Ø =

ÑaØch Ø ÛiØh

ÌÑÎaÖ´fi¸i¸_µ !

geØØÝÔe fi cØÜ i

| ÌÑAb×´fi¸Ü¸ØÝ˸ؽµ !

ÐeØ cØܳ = addbiÒdiÒg cØÜ Ü ´ÎaÖBiÒd´ØÝ˵µ iÒ

ÐeØ ØÝÌ = ØÝÔeÓf cØܳ ؽ iÒ

ÌÝAÖÖ´ØÝ˸ ØÝ×hifØ ØÝÌ ´¹½µµ

| ÌÑAÔÔ´fi¸Ø½¸Ø¾µ !

ÐeØ ØÝ̽ = ØÝÔeÓf cØÜ Ø½ iÒ

ÐeØ ØÝ̾ = ØÝÔeÓf cØÜ Ø¾ iÒ

´ÑaØch ØÝ̽ ÛiØh

ÌÝAÖÖ´ØÝ̽½¸ØÝ̽¾µ !

if ØÝeÕÚ ØÝ̾ ØÝ̽½ ØheÒ ØÝ̽¾

eÐ×e eÖÖÓÖ fi "ÔaÖaÑeØeÖ ØÝÔe Ñi×ÑaØch"

| _ ! eÖÖÓÖ fi "aÖÖÓÛ ØÝÔe eÜÔecØed"µ

| ÌÑÌÖÙe´fiµ !

ÌÝBÓÓÐ

| ÌÑFaÐ×e´fiµ !

ÌÝBÓÓÐ

| ÌÑÁf´fi¸×½¸×¾¸×¿µ !

if ØÝeÕÚ ´ØÝÔeÓf cØÜ ×½µ ÌÝBÓÓÐ ØheÒ

ÐeØ ØÝË = ØÝÔeÓf cØÜ ×¾ iÒ

if ØÝeÕÚ ØÝË ´ØÝÔeÓf cØÜ ×¿µ ØheÒ ØÝË

eÐ×e eÖÖÓÖ fi "aÖÑ× Óf cÓÒdiØiÓÒaÐ haÚe diffeÖeÒØ ØÝÔe×"

eÐ×e eÖÖÓÖ fi "gÙaÖd Óf cÓÒdiØiÓÒaÐ ÒÓØ a bÓÓÐeaÒ" January 15, 2000 7. SIMPLY TYPED LAMBDA-CALCULUS 66

7.6 Further Reading

The untyped lambda-calculus was developed by Church and his co-workers in the 1930s [Chu41]. The standard text for all aspects of the untyped lambda-calculus is Barendregt [Bar84]. Hindley and Seldin [HS86] is less comprehensive, but some- what more accessible. Barendregt’s article in the Handbook of Theoretical Com- puter Science [Bar90] is a compact survey. The simply typed lambda-calculus is studied in Hindley and Seldin [HS86] and in even greater detail in Hindley’s more recent book [Hin97]. Material on both typed and untyped lambda-calculus can also be found in many textbooks on functional programming languages (e.g. [PJL92]) and programming language semantics (e.g.[Sch86, Gun92, Win93, Mit96]). Chapter 8

Extensions

This chapter is just a sketch (but all the underlying implementations are finished, so it won’t be too hard to fill in). It presents a bunch of familiar typing features and program- ming language constructs and shows how they fit into the framework we’ve built. There should be lots of exercises.

8.1 Base Types B Base types !

New syntactic forms

Ì ::= ... (types...)

B base type

8.2 Unit type ÍÒiØ Unit type !

New syntactic forms

Ø ::= ... (terms...) ÙÒiØ ÙÒiØ constant

Ì ::= ... (types...)

67 January 15, 2000 8. EXTENSIONS 68

ÍÒiØ unit type

` Ø : Ì

New typing rules ( )

` ÙÒiØ : ÍÒiØ

(T-UNIT) ÍÒiØ Note: C and Java’s ÚÓid type is a misnomer – what they really mean is

8.3 Let bindings ÐeØ Let binding !

New syntactic forms

Ø ::= ... (terms...)

Ü=Ø iÒ Ø

ÐeØ let binding

¼

! Ø

New evaluation rules (Ø )

ÐeØ Ü=Ú iÒ Ø ! fÜ 7! Ú gØ

¾ ½ ¾

½ (E-LETBETA)

¼

Ø ! Ø ½

½ ET

¼ (E-L )

ÐeØ Ü=Ø iÒ Ø ! ÐeØ Ü=Ø iÒ Ø

½ ¾ ¾

½

` Ø : Ì

New typing rules ( )

` Ø : Ì ; Ü:Ì ` Ø : Ì

½ ½ ¾ ¾

½ (T-LET)

` ÐeØ Ü=Ø iÒ Ø : Ì

½ ¾ ¾ ×iÑÔÐe 8.3.1 Exercise [Recommended]: Add ÐeØ bindings to the “ ” typechecker

implementation. (Solution on page ??.) ¾

8.4 Records and Tuples

January 15, 2000 8. EXTENSIONS 69 fg Records and tuples !

New syntactic forms

Ø ::= ... (terms...)

i¾½::Ò

ßÐ =Ø } i i record

غРprojection

Ú ::= ... (values...)

i¾½::Ò

ßÐ =Ú } i i record value

Ì ::= ... (types...)

i¾½::Ò

ßÐ :Ì } i

i type of records

¼

! Ø

New evaluation rules (Ø )

i¾½::Ò

ßÐ =Ú }ºÐ ! Ú

i i i

i (E-RCDBETA)

¼

Ø ! Ø ½

½ ROJ

¼ (E-P )

Ø ºÐ ! Ø ºÐ

½

½

¼

Ø ! Ø j

j (E-RECORD)

i¾ ½::j¹½ ¼ k¾j·½::Ò i¾½::Ò

¸Ð =Ø } } ! ßÐ =Ú ¸Ð =Ø ßÐ =Ú

j i i k k i i

j

` Ø : Ì

New typing rules ( )

i ` Ø : Ì i for each i

(T-RCD)

i¾½::Ò i¾½::Ò

` ßÐ =Ø } : ßÐ :Ì }

i i i i

i¾½::Ò

` Ø : ßÐ :Ì } i

i (T-PROJ)

` غР: Ì

j j New abbreviations

def

ߺººØ ººº} = ߺººi=Ø ººº}

i i

def

ߺººÌ ººº} = ߺººi:Ì ººº}

i i

8.4.1 Exercise: In this presentation of records, the projection operation is used to extract the fields of a record one by one. Many high-level programming languages provide an alternative pattern matching syntax that extracts all the fields at the same time, allowing many programs to be expressed more concisely. Patterns can typically be nested, allowing parts to be extracted easily from complex nested data structures. For example, we can add a simple form of pattern matching to the untyped lambda calculus with records by adding a new syntactic category of patterns, plus January 15, 2000 8. EXTENSIONS 70 one new case (for the pattern matching construct itself) to the syntax of terms. To define the computation rule for pattern matching, we need an auxiliary “match- ing” function. Given a pattern and a term, the pattern matching function either fails (if the term does not match the pattern) or else yields a substitution that re- places variables appearing in the pattern with the corresponding subterms of the given term. Here is the formal definition of the calculus, highlighting differences from the pure untyped lambda-calculus with records and ordinary let-binding:

January 15, 2000 8. EXTENSIONS 71

fg ÐeØ Record patterns ! pat (untyped)

New syntactic forms ::: Ô ::=

Ü variable pattern

i¾½::Ò

ßÐ =Ô } i i record pattern

Ø ::= ... (terms...)

Ô=Ø iÒ Ø ÐeØ pattern binding

Matching rules:

Ü; ص=fÜ 7! Øg

match´ (M-VAR)

i ´Ô ; Ø µ=

i i for each match i

(M-RCD)

i¾½::Ò i¾½::Ò

´ßÐ =Ô }; ßÐ =Ø }µ =  Æ ¡¡¡ Æ 

i i i i Ò

match ½

¼

! Ø

New evaluation rules (Ø )

ÐeØ Ô=Ú iÒ Ø ! ´Ô; Ú µ Ø

¾ ½ ¾

½ match (E-LETBETA)

¼

Ø ! Ø

½ ½

(E-LET)

¼

ÐeØ Ô=Ø iÒ Ø ! ÐeØ Ô=Ø iÒ Ø

½ ¾ ¾ ½ New abbreviations

def

ߺººÔ ººº} = ߺººi=Ô ººº}

i i

Your job is to add types to this calculus, in the style of the simply typed lambda- calculus: 1. Give typing rules for the new constructs (making any changes to the syntax you feel are necessary in the process). 2. Sketch a proof of type preservation and progress for the whole calculus by stating the sequence of major lemmas needed to carry out the proof. (You do not need to show proofs, just statements of the required lemmas in the correct order.)

(Solution on page 256.) ¾ January 15, 2000 8. EXTENSIONS 72

8.5 Variants <> Variants !

New syntactic forms

Ø ::= ... (terms...)

a× Ì

<Ð=Ø> tagging

ca×e Ø Óf ººº | Ð =ÜµØ | ººº i i case

Ì ::= ... (types...)

i¾½::Ò

<Ð :Ì > i

i type of variants

¼

! Ø

New evaluation rules (Ø )

ca×e <Ð =Ú > a× Ì Óf ººº|Ð =ÜµØ |ººº ! fÜ 7! Ú gØ

i i i i i

i (E-CASEBETA)

¼

× ! × ½

½ ASE

¼ (E-C )

ca×e × Óf ººº|Ð =ÜµØ |ººº ! ca×e × Óf ººº|Ð =ÜµØ |ººº

½ i i i i

½

¼

Ø ! Ø i

i (E-TAG)

¼

<Ð =Ø > a× Ì ! <Ð =Ø > a× Ì

i i i

i

` Ø : Ì

New typing rules ( )

i ` Ø : Ì i for each i

(T-VARIANT)

i¾½::Ò i¾ ½::Ò

> > : <Ð :Ì ` <Ð =Ø > a× <Ð :Ì

i i i i i i

i¾½::Ò

` Ø : <Ð :Ì >

¼ i i

i ; Ü :Ì ` Ø : Ì

i i for each i

(T-CASE)

` ca×e Ø Óf ººº|Ð =Ü µØ |ººº : Ì

¼ i i i

Note that we syntactically allow the type label to be a non-, but the typing rule then excludes this case. This is just for brevity (and implementation flexibility, e.g. when we get to definitions).

8.6 General recursion

January 15, 2000 8. EXTENSIONS 73 fiÜ General recursion !

New syntactic forms

Ø ::= ... (terms...)

Ø Ø

fiÜ fixed point of

` Ø : Ì

New typing rules ( )

` Ø : Ì !Ì

½ ½

½ (T-FIX)

` fiÜ Ø : Ì

½ ½ New abbreviations

def

ÐeØÖec Ü=Ø iÒ Ø = ÐeØ Ü = fiÜ ´ÜºØ µ iÒ Ø

½ ¾ ½ ¾

A corollary of the definability of fixed-point combinators at every type is that

every type in this system is inhabited. For example, for each type Ì, the application

´diÚeÖge ÙÒiص Ì diÚeÖge Ì

Ì has type , where is defined like this:

diÚeÖge = _:ÍÒiغ fiÜ ´Ü:̺ ܵ;

Ì

Á

Ì = ÆaØ: ¶

diÚeÖge : ÍÒiØ ! Ì Ì

8.7 Lists

B Äi×Ø Lists !

New syntactic forms

Ø ::= ... (terms...) [Ì]

ÒiÐ empty list

[Ì] Ø Ø

cÓÒ× list constructor

[Ì] Ø

ÒÙÐÐ test for empty list

[Ì] Ø

head head of a list

[Ì] Ø ØaiÐ tail of a list

Ú ::= ... (values...) [Ì]

ÒiÐ empty list

[Ì] Ú Ú cÓÒ× list constructor

Ì ::= ... (types...) Ì

Äi×Ø type of lists

¼

! Ø New evaluation rules (Ø )

January 15, 2000 8. EXTENSIONS 74

¼

Ø ! Ø ½

½ (E-CONS1)

¼

cÓÒ×[Ì] Ø Ø ! cÓÒ×[Ì] Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø ¾

¾ (E-CONS2)

¼

cÓÒ×[Ì] Ú Ø ! cÓÒ×[Ì] Ú Ø

½ ¾ ¾

½

´ÒiÐ[Ì]µ ! ØÖÙe

ÒÙÐÐ[Ë] (E-NULLBETAT)

ÒÙÐÐ[Ë] ´cÓÒ×[Ì] Ú Ú µ ! faÐ×e ¾

½ (E-NULLBETAF)

¼

Ø ! Ø ½

½ ULL

¼ (E-N )

ÒÙÐÐ[Ì] Ø ! ÒÙÐÐ[Ì] Ø

½

½

head[Ë] ´cÓÒ×[Ì] Ú Ú µ ! Ú

¾ ½

½ (E-HEADBETA)

¼

Ø ! Ø ½

½ EAD

¼ (E-H )

head[Ì] Ø ! head[Ì] Ø

½

½

ØaiÐ[Ë] ´cÓÒ×[Ì] Ú Ú µ ! Ú

¾ ½

½ (E-TAILBETA)

¼

Ø ! Ø ½

½ AIL

¼ (E-T )

ØaiÐ[Ì] Ø ! ØaiÐ[Ì] Ø

½

½

` Ø : Ì

New typing rules ( )

` ÒiÐ [Ì] : Äi×Ø Ì

(T-NIL)

` Ø : Ì ` Ø : Äi×Ø Ì

½ ¾ ½

½ (T-)

` cÓÒ× Ø Ø : Äi×Ø Ì

½ ¾ ½

` Ø : Äi×Ø Ì ½

½ (T-NULL)

` ÒÙÐÐ Ø : BÓÓÐ

½

` Ø : Äi×Ø Ì ½

½ (T-HEAD)

` head Ø : Ì

½ ½

` Ø : Äi×Ø Ì ½

½ (T-TAIL)

` ØaiÐ Ø : Äi×Ø Ì

½ ½ January 15, 2000 8. EXTENSIONS 75

8.8 Lazy records and let-bindings

ÐeØ ÐaÞÝ Lazy let bindings !

New syntactic forms

Ø ::= ... (terms...)

ÐeØ Ü=Ø iÒ Ø

ÐaÞÝ lazy let binding

¼

! Ø

New evaluation rules (Ø )

ÐaÞÝ ÐeØ Ü=Ø iÒ Ø ! fÜ 7! Ø gØ

¾ ½ ¾

½ (E-LLETBETA)

` Ø : Ì

New typing rules ( )

` Ø : Ì ; Ü:Ì ` Ø : Ì

½ ½ ¾ ¾

½ (T-LLET)

` ÐaÞÝ ÐeØ Ü=Ø iÒ Ø : Ì

½ ¾ ¾

fg ÐaÞÝ Lazy records !

New syntactic forms

Ø ::= ... (terms...)

i¾ ½::Ò

} ÐaÞÝ ßÐ =Ø i i lazy record

Ú ::= ... (values...)

i¾ ½::Ò

ÐaÞÝ ßÐ =Ø } i

i lazy record value

¼

! Ø

New evaluation rules (Ø )

i¾½::Ò

}µºÐ ! Ø ´ÐaÞÝ ßÐ =Ø

i i i

i (E-LRCDBETA)

` Ø : Ì

New typing rules ( )

i¾½::Ò

` Ø : Ì i

i (T-LRCD)

i¾½::Ò i¾½::Ò

` ÐaÞÝ ßÐ =Ø } : ßÐ :Ì }

i i i i

Exercise: write down rules for lazy functions (These are used only in the advanced parts of the object examples.) Chapter 9

References

This chapter is still very rough. The basic approach seems fine, but there’s a good deal of

work to do on details.

ÍÒiØ := References !

Syntax

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø

Ø application ÙÒiØ ÙÒiØ constant

Ð store location Ø Öef reference creation

!Ø dereference

Ø:=Ø assignment

Ú ::= (values...)

Ü:ÌºØ  abstraction value

Ð store location

Ì ::= (types...)

!Ì Ì type of functions

ÍÒiØ unit type

Êef Ì

½ type of reference cells

::= (contexts...)

; empty context Ü:Ì ; term variable binding

76

January 15, 2000 9. REFERENCES 77 ;

 ::= empty store

= Ø

; Ð location binding ;

¦ ::= empty store typing :Ì

¦; Ð location typing

¼ ¼

j  ! Ø j 

Evaluation (Ø )

´Ü :Ì ºØ µ Ú j  ! fÜ 7! Ú gØ j 

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼ ¼

Ø j  ! Ø j 

½ ½

(E-APP1)

¼ ¼

Ø Ø j  ! Ø Ø j 

½ ¾ ¾

½

¼ ¼

Ø j  ! Ø j 

¾ ¾

(E-APP2)

¼ ¼

Ú Ø j  ! Ú Ø j 

½ ¾ ½

¾

¾ ´µ Ð=dom

(E-REF)

Öef Ú j  ! Ð j ´; Ð = Ú µ

½ ½

¼ ¼

Ø j  ! Ø j  ½

½ (E-REF1)

¼ ¼

Öef Ø j  ! Öef Ø j 

½

½

´Ðµ=Ú

(E-DEREF)

!Ð j  ! Ú j 

¼ ¼

j  Ø j  ! Ø ½

½ (E-DEREF1)

¼ ¼

j  !Ø j  ! !Ø

½

½

Ð:=Ú j  ! ÙÒiØ jfÐ 7! Ú g ¾

¾ (E-ASSIGN)

¼ ¼

Ø j  ! Ø j  ½

½ (E-ASSIGN1)

¼ ¼

Ø :=Ø j  ! Ø :=Ø j 

½ ¾ ¾

½

¼ ¼

Ø j  ! Ø j  ¾

¾ SSIGN

¼ ¼ (E-A 2)

Ú :=Ø j  ! Ú :=Ø j 

½ ¾ ½

¾

j ¦ ` Ø : Ì

Typing ( )

Ü:Ì ¾

(T-VAR)

j ¦ ` Ü : Ì

; Ü:Ì j ¦ ` Ø : Ì

½ ¾ ¾

(T-ABS)

j ¦ ` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

January 15, 2000 9. REFERENCES 78

j ¦ ` Ø : Ì !Ì j ¦ ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

j ¦ ` Ø Ø : Ì

½ ¾ ½¾

j ¦ ` ÙÒiØ : ÍÒiØ

(T-UNIT)

¦´Ðµ=Ì

(T-LOC)

j ¦ ` Ð : Êef Ì

j ¦ ` Ø : Ì ½

½ (T-REF)

j ¦ ` Öef Ø : Êef Ì

½ ½

j ¦ ` Ø : Êef Ì ½

½ (T-DEREF)

j ¦ ` !Ø : Ì

½ ½

j ¦ ` Ø : Êef Ì j ¦ ` Ø : Ì

½ ¾ ½

½ (T-ASSIGN)

j ¦ ` Ø :=Ø : ÍÒiØ

½ ¾

9.1 Definition: We say that a store  is well-typed with respect to a typing context

¦ j ¦ `  ´µ= ´¦µ j ¦ ` ´Ðµ : ¦´Ðµ

and a store typing , written ,ifdom dom and

¾ ´µ ¾

for every Ð dom .

Ü:Ë;¦` Ø : Ì j ¦ ` × : Ë j ¦ ` fÜ 7!

9.2 Lemma [Substitution]: If ; and , then

gØ : Ì ¾ × .

Proof: Just like the proof of Lemma 7.4.9. ¾

¼ ¼

j ¦ ` Ø : Ì ¦  ¦ ; ¦ ` Ø : Ì ¾ 9.3 Lemma: If and , then .

Proof: Easy. ¾

9.4 Theorem [Preservation]: If

j ¦ ` Ø : Ì

j ¦ ` 

£ ¼ ¼

Ø j  ! Ø j 

¼

 ¦

then, for some ¦ ,

¼ ¼

j ¦ ` Ø : Ì

¼ ¼

j ¦ `  ¾ . Proof: Clearly, the preservation property for multi-step evaluation will follow (by

a straightforward induction) from preservation for single-step evaluation. This,

£ ¼ ¼

j  ! Ø j  in turn, is established by an induction on a derivation of Ø . All the cases of this induction are straightforward, using the lemmas above and the

evident inversion property of the typing rules. ¾ 9.5 Exercise: Is the evaluation relation defined in this chapter strongly normaliz-

ing on well-typed terms? (Solution on page 260.) ¾ January 15, 2000 9. REFERENCES 79

9.1 Further Reading

The presentation of references in this chapter is adapted from Harper’s treatment [?]. An earlier account in a similar style is given by Wright and Felleisen [?]. The combination of references (or other computational effects) with ML-style polymorphic type inference (cf. Section ??) raises some subtle problems and has received a good deal of attention in the research literature. See [Tof90, HMV93, JG91, TJ92, TJ92, LW91, Wri92] and the references cited there. Chapter 10

Exceptions

I’m not sure whether the amount of material here warrants a separate chapter, or just a section in Chapter 8.

10.1 Errors 10.2 Exceptions

80 Chapter 11

Type Equivalence

To be written. The point of introducing equivalence as a separate notion is that it gives a uniform framework for all kinds of definitional equivalences on types. It introduces a bit of overhead too, but I think it’s worth it in this case. This chapter has just been added, and some of the later chapters have not been brought

up to date (the equivalence rules used to be folded into the subtyping relation).

fg 

Records with permutation of fields !

 Ì

Type equivalence (Ë )

 Ì

Ì (Q-REFL)

Ì  Ë

(Q-SYMM)

Ë  Ì

Ë  Í Í  Ì

(Q-TRANS)

Ë  Ì

Ë  Ì Ë  Ì

½ ¾ ¾

½ (Q-ARROW)

Ë !Ë  Ì !Ì

½ ¾ ½ ¾

f½::Òg  is a permutation of

CD ERM

i¾½::Ò

¾ ½::Ò i (Q-R -P )

ßÐ :Ì }  ßÐ :Ì }

i i i

i

` Ø : Ì

New typing rules ( )

` Ø : Ë Ë  Ì

(T-EQ)

` Ø : Ì

81

January 15, 2000 11. TYPE EQUIVALENCE 82 B

Algorithmic rules for simply typed lambda-calculus !

Á

` Ø : Ì

Algorithmic typing ( )

Ü:Ì ¾

(TA-VAR)

Á

` Ü : Ì

Á

; Ü:Ì ` Ø : Ì

¾ ¾

½ (TA-ABS)

Á

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

Á Á

` Ø : Ì Ì = Ì !Ì ` Ø : Ì Ì = Ì

½ ½ ½½ ½¾ ¾ ¾ ¾ ½½

½ (TA-APP)

Á

` Ø Ø : Ì

½ ¾ ½¾

fg 

Algorithmic rules for records with permutation !

Á

Ë  Ì

Algorithmic type equivalence (` )

Á Á

` Ë  Ì ` Ë  Ì

½ ¾ ¾

½ (QA-ARROW)

Á

` Ë !Ë  Ì !Ì

½ ¾ ½ ¾

f½::Òg

 is a permutation of

Á

i ` Ì  Ì i for each i

CD

¾½::Ò

i (QA-R )

i¾½::Ò

Á

` ßÐ :Ì }  ßÐ :Ì }

i i i

i

Á

` Ø : Ì

Algorithmic typing ( )

Ü:Ì ¾

(TA-VAR)

Á

` Ü : Ì

Á

; Ü:Ì ` Ø : Ì

¾ ¾

½ (TA-ABS)

Á

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

Á Á Á

` Ø : Ì Ì = Ì !Ì ` Ø : Ì ` Ì  Ì

½ ½ ½½ ½¾ ¾ ¾ ¾ ½½

½ (TA-APP)

Á

` Ø Ø : Ì

½ ¾ ½¾

Á

i ` Ø : Ì i for each i

(TA-RCD)

Á

` ßÐ =Ø ºººÐ =Ø } : ßÐ :Ì ºººÐ :Ì }

½ ½ Ò Ò ½ ½ Ò Ò

Á

` Ø : ßÐ :Ì ºººÐ :Ì }

½ Ò Ò

½ (TA-PROJ)

Á

` غР: Ì

i i Chapter 12

Definitions

12.1 Type Definitions

(needed for equirec implementation stuff) introduce type variables (this section is optional, so we need to re-introduce them when we get to polymporphism) extend type equivalence relation talk about exposing types before matching against them Exercise: inner defns (not trivial: must eliminate remaining occurrences when

leaving the scope of the definition)

B ° Type definitions !

New syntactic forms

Ì ::= ... (types...)

X

::= ... (contexts...)

X°Ì

; type definition binding

` Ë  Ì

New type equivalence rules ( )

` Ì  Ì

(Q-REFL)

` Ì  Ë

(Q-SYMM)

` Ë  Ì

` Ë  Í ` Í  Ì

(Q-TRANS)

` Ë  Ì

83

January 15, 2000 12. DEFINITIONS 84

` Ë  Ì ` Ë  Ì

½ ½ ¾ ¾

(Q-ARROW)

` Ë !Ë  Ì !Ì

½ ¾ ½ ¾

X°Ì ¾

(Q-DEF)

` X  Ì

` Ø : Ì

New typing rules ( )

` Ø : Ë ` Ë  Ì

(T-EQ)

` Ø : Ì

B °

Algorithmic rules for type definitions !

¼

Á

` Ì  Ì

Algorithmic reduction ( )

X°Ì ¾

(RA-DEF)

` X  Ì

Á

` Ë  Ì

Algorithmic type equivalence ( )

Á

` B  B

(QA-BASE)

¼ ¼

Á Á

` Ë  Ë ` Ë  Ì

(QA-REDUCEL)

Á

` Ë  Ì

¼ ¼

Á Á

` Ì  Ì ` Ë  Ì

(QA-REDUCER)

Á

` Ë  Ì

Á Á

` Ë  Ì ` Ë  Ì

½ ½ ¾ ¾

(QA-ARROW)

Á

` Ë !Ë  Ì !Ì

½ ¾ ½ ¾

¼

Á

` Ì ¶ Ì Exposure ( ) otherwise

(XA-OTHER)

Á

` Ì ¶ Ì

¼ ¼ ¼¼

Á Á

` Ì  Ì ` Ì ¶ Ì

(XA-REDUCE)

¼¼

Á

` Ì ¶ Ì

Á

` Ø : Ì

Algorithmic typing ( )

Ü:Ì ¾

(TA-VAR)

Á

` Ü : Ì

Á

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(TA-ABS)

Á

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

January 15, 2000 12. DEFINITIONS 85

Á Á Á Á

` Ø : Ì ` Ì ¶ ´Ì !Ì µ ` Ø : Ì ` Ì  Ì

½ ½ ½ ½½ ½¾ ¾ ¾ ¾ ½½

Á

` Ø Ø : Ì

½ ¾ ½¾ (TA-APP)

12.2 Term Definitions

(This should be very optional, but it’s nice to be honest about what the checkers are doing.) Chapter 13

Subtyping

This material is not too far from finished, but the proofs and presentation need to be re- worked a little in light of the addition of Chapter 11.

In programming in the simply typed lambda-calculus, we may sometimes find ourselves irritated by the type system’s insistence that types match exactly, for

example in the rule T-APP for typing applications:

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

According to this rule, the term

´Ö:ßÜ:ÆaØ}º ֺܵ ßÜ=¼¸ Ý=½} is not typeable, even though it will obviously evaluate without producing any

run-time errors, since the function only requires that its argument has a field Ü;it doesn’t care what other fields the argument may or may not have. Moreover, this fact is evident from the type of the function—we don’t need to look at its body to

see that it doesn’t use any fields besides Ü.

One way to formalize this observation is to extend the typing rules so that

Ý=¼} ßÜ:Æaظ Ý:ÆaØ} the term ßÜ=¼¸ is given a set of types including both and

ßÜ:ÆaØ}. Then the application above is well typed because one of the possible types of the argument matches the left-hand side of the type of the function.

To accomplish this in a general way, we introduce a principle of safe substitu-

Ì Ë <: Ì

tion: We say that “Ë is a subtype of ,” written , to mean that any term of Ì

type Ë can safely be used in a context where a term of type is required. If this is

Ë Ì the case, then a term Ø of type is also given the type , using the so-called rule of

subsumption:

` Ø : Ë `Ë <: Ì

(T-SUB)

` Ø : Ì

86 January 15, 2000 13. SUBTYPING 87

No other changes are needed to the typing relation (though, as we shall see in Section 13.2, some changes are required to the algorithmic implementation of the typing relation). It remains only to formalize the subtype relation.

In this chapter, we’ll mainly work with a calculus with just records and func-

<:fg tions (written  , for short), which is rich enough to bring out most of the inter- esting issues. Examples and exercises will touch on the combination of subtyping with most of the other features we have seen.

13.1 The Subtype Relation

Clearly, it is not safe to substitute functions for records, records for functions, etc. The subtyping relation will only be defined for types with similar structure. First, just to make sure that our subtyping relation is sensible, we make two general stipulations: first, that it should be reflexive,

and second, that it should be transitive:

`Ë <: Í `Í <: Ì

(S-TRANS)

`Ë <: Ì These rules follow directly from the intuition of safe substitutivity. The remainder of the rules defining the subtype relation concern the behavior of specific type

constructors. =

For record types, we have already seen that we want to consider the type Ë

ßk :Ë ºººk :Ë } Ì = ßÐ :Ì ºººÐ :Ì } Ì

½ Ñ Ñ ½ ½ Ò Ò ½ to be a subtype of if is obtained by

dropping fields from Ë.

i¾ ½::Ò·k i¾½::Ò

`ßÐ :Ì } <: ßÐ :Ì }

i i i i (S-RCD-WIDTH)

In fact, we can be a little more general than this and also allow the types of the Ì

common fields to differ, so long as their types in Ë are subtypes of their types in .

i `Ë <: Ì i for each i

(S-RCD-DEPTH)

i¾ ½::Ò i¾½::Ò

} } <: ßÐ :Ì `ßÐ :Ë

i i i i Also, it makes sense to ignore the order of fields in a record, since the only thing that we can do with records—namely, field projection—is insensitive to the order of fields.

For functions, the rule is a little trickier:

`Ì <: Ë `Ë <: Ì

½ ½ ¾ ¾

(S-ARROW)

`Ë !Ë <: Ì !Ì

½ ¾ ½ ¾ That is, we allow a function of one type to be used where another is expected as

long as none of the arguments that may be passed to the function by the context

Ì <: Ë ½

will surprise it ( ½ ) and none of the results that it returns will surprise the

Ë <: Ì ¾ context ( ¾ ). Notice that the sense of the subtype relation is reversed on the left of the arrow; this rule is sometimes referred to as the “contravariant arrow rule” for this reason. January 15, 2000 13. SUBTYPING 88

13.1.1 Exercise [Quick check]: Demonstrate that the premises of S-ARROW are both necessary by giving ill-behaved programs that would be well typed if either premise

were dropped. ¾

Finally, for various reasons, it will be convenient to have a type that is a super-

type of every type. We introduce a new type constant ÌÓÔ for this purpose, plus a

rule that makes ÌÓÔ maximal in the subtype relation.

`Ë <: ÌÓÔ (S-TOP) Formally, the subtype relation is the least relation closed under the rules we have given.

13.1.2 Exercise [Quick check]: In a system with reference cells, would it be a good

idea to add a rule

Ë <: Ì

Êef Ë <: Êef Ì

for subtyping between reference cell types? ¾

Variance We pause for a moment to introduce some useful terminology for discussing types

and subtyping.

[] [] Suppose Ì is a type term containing some number of holes, written “ ” some-

place inside it; we write ̴˵ for the term that results from filling the holes in

Ë Ì[] = ßÜ:ÌÓÔ¸Ý:[]}!ÌÓÔ![]!ÆaØ Ì´Æaص =

Ì with . For example, if , then

!ÌÓÔ!ÆaØ!ÆaØ

ßÜ:ÌÓÔ¸Ý:ÆaØ} . []

We say that Ì is covariant in the position(s) marked by the holes if, whenever

Ë <:Ë Ì´Ë µ <: Ì´Ë µ Ì[]

¾ ½ ¾

½ , we have . We say that is contravariant if, whenever

Ë <:Ë Ì´Ë µ <: Ì´Ë µ Ì[]

¾ ¾ ½ ½ , we have .If is neither covariant nor contravariant,

it is said to be invariant. For example, we say that the arrow type constructor

is contravariant in its first argument and covariant in its second, since [] is

![] contravariant while Ë is covariant.

13.1.3 Exercise: Which of the following types are covariant in the position marked

by the hole(s)? Which are contravariant? Which are invariant?

[]=[]!ÌÓÔ

1. Ì

[] = ÌÓÔ![]

2. Ì

[] = ßÜ:ÌÓÔ¸Ý:[]}!ÆaØ!ÆaØ

3. Ì

[]=[]!ÌÓÔ!ÌÓÔ

4. Ì

[] = ´[]!ÌÓÔµ!ÌÓÔ 5. Ì

January 15, 2000 13. SUBTYPING 89

[]=[]!ÆaØ![]

6. Ì []=[]

7. Ì

[] = ÆaØ ¾ 8. Ì

Summary As usual, we present the subtyping extension of the pure simply typed lambda

calculus first, then the additional rules for records.

 ! <:

<: : Simply typed lambda-calculus with subtyping

Syntax

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø Ø application

Ú ::= (values...)

Ü:ÌºØ  abstraction value

Ì ::= (types...)

!Ì Ì type of functions

ÌÓÔ maximum type

::= (contexts...)

; empty context Ü:Ì

; term variable binding

¼

! Ø

Evaluation (Ø )

´Ü:Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

<: Ì

Subtyping (Ë )

<: Ë

Ë (S-REFL)

Ë <: Í Í <: Ì

(S-TRANS)

Ë <: Ì

January 15, 2000 13. SUBTYPING 90

<: ÌÓÔ

Ë (S-TOP)

Ì <: Ë Ë <: Ì

½ ¾ ¾

½ (S-ARROW)

Ë !Ë <: Ì !Ì

½ ¾ ½ ¾

` Ø : Ì

Typing ( )

Ü:Ì ¾

(T-VAR)

` Ü : Ì

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

` Ø : Ë Ë <: Ì

(T-SUB)

` Ø : Ì

<: fg

Subtyping rules for records !

 Ì

New type equivalence rules (Ë )

 Ì

Ì (Q-REFL)

Ì  Ë

(Q-SYMM)

Ë  Ì

Ë  Í Í  Ì

(Q-TRANS)

Ë  Ì

Ë  Ì Ë  Ì

½ ¾ ¾

½ (Q-ARROW)

Ë !Ë  Ì !Ì

½ ¾ ½ ¾

f½::Òg  is a permutation of

CD ERM

¾½::Ò

i (Q-R -P )

i¾ ½::Ò

}  ßÐ :Ì } ßÐ :Ì

i i i

i

<: Ì

New subtyping rules (Ë )

Ë  Ì

(S-EQV)

Ë <: Ì

i¾½::Ò·k i¾½::Ò

ßÐ :Ì } <: ßÐ :Ì }

i i i

i (S-RCD-WIDTH)

i Ë <: Ì i for each i

(S-RCD-DEPTH)

i¾½::Ò i¾½::Ò

ßÐ :Ë } <: ßÐ :Ì }

i i i i January 15, 2000 13. SUBTYPING 91

13.1.4 Exercise: What should the subtyping rules for variants be? ¾ ß} 13.1.5 Exercise: In what ways are the ÌÓÔ type and the empty record type simi-

lar? In what ways are they different? ¾

13.2 Metatheory of Subtyping

First, show that type equivalence can be deleted by merging with the record rule as below.

Then proceed as before.

!fg<: In this section we consider some of the properties of the system  , the simply typed lambda-calculus with records and subtyping.

Algorithmic Subtyping The three rules for record subtyping are often combined into one more compact

but less readable rule:

j¾½::Ñ i¾½::Ò

g k = Ð g  fk fÐ Ë <: Ì

j i j j i i implies

(S-RCD)

j¾½::Ñ i¾½::Ò

ßk :Ë } <: ßÐ :Ì }

j j i i

13.2.1 Lemma: This rule can be derived from S-RCD-DEPTH, S-RECORD-WIDTH,

and S-RECORD-PERM (using reflexivity and transitivity) and vice versa. ¾

Proof: Exercise. ¾

We now observe that the rules of reflexivity and transitivity are inessential, in the following sense:

13.2.2 Lemma:

<: Ë Ë

1. Ë can be derived for every type without using S-REFL.

<: Ì ¾ 2. If Ë can be derived at all, then it can be derived without using S-TRANS.

Proof: Exercise. ¾

13.2.3 Exercise [Quick check]: If we add ÆaØ to the type system, how do these

properties change? ¾

13.2.4 Definition: The algorithmic subtyping relation is the least relation closed under the following rules:

January 15, 2000 13. SUBTYPING 92

fg <:

Algorithmic subtyping !

Á

Ë <: Ì

Algorithmic subtyping (` )

Á

Ë <: ÌÓÔ

` (SA-TOP)

Á Á

` Ì <: Ë ` Ë <: Ì

½ ¾ ¾

½ (SA-ARROW)

Á

` Ë !Ë <: Ì !Ì

½ ¾ ½ ¾

i¾½::Ò j¾½::Ñ

Á

fÐ k = Ð ` Ë <: Ì g  fk g

i j i j i j if , then

(SA-RCD)

j¾½::Ñ i¾½::Ò

Á

` ßk :Ë } <: ßÐ :Ì }

j j i i ¾

13.2.5 Proposition [Soundness and completeness of algorithmic subtyping]:

Ë <: Ì Ë <: Ì ¾

iff a .

Proof: Using the two previous lemmas. ¾

This, in turn, leads directly to an algorithm for checking the algorithmic sub-

type relation (and hence also the declarative subtype relation, by Proposition 13.2.5).

Ë; ̵ Ì = ÌÓÔ subtype´ =if ,

then true

Ë = Ë !Ë Ì = Ì !Ì

¾ ½ ¾

else if ½ and

´Ì ; Ë µ ^ ´Ë ; Ì µ

½ ¾ ¾

then subtype ½ subtype

j¾½::Ñ i¾ ½::Ò

Ë = ßk :Ë } Ì = ßÐ :Ì }

j i i

else if j and

¾ ½::Ò

then, for all i ,

j k = Ð i

find such that j and check

´Ë ; Ì µ i subtype j else false.

Minimal Typing By introducing the rule of subsumption into the typing relation, we have lost the useful syntax-directedness property, which in the simply typed lambda-calculus

allows a typechecker to be implemented simply by “reading the rules from bottom

` Ø : Ì to top.” Without this property, how can we now check whether is a derivable statement? We do it in two steps:

1. Find another set of syntax rules that are syntax directed, defining a relation

Á

` Ø : Ì . This is called the algorithmic typing relation. January 15, 2000 13. SUBTYPING 93

2. Show that, although they are defined differently, the ordinary typing relation

Á

` Ø : Ì ` Ø : Ì and the algorithmic typing relation give rise to the same set of typable terms. Interestingly, though, they will not assign exactly the same types to those terms. In order to find an algorithmic presentation of the typing relation, we need to think carefully about the structure of typing derivations to see where the rule of subsumption is really needed, and where we could just as well do without it. For example, consider the following derivation: . .

. .

¼

; Ü:Ë ` Ø : Ì Ì <: Ì µ

´ T-SUB

¼

; Ü:Ë ` Ø : Ì µ

´ T-ABS

¼

` Ü:輯 : Ë!Ì Any such derivation can be rearranged like this: . .

. . µ

´ S-REFL

¼

; Ü:Ë ` Ø : Ì Ì <: Ì Ë <: Ë

µ ´ µ

´ T-ABS S-ABS

¼

` Ü:輯 : Ë!Ì Ë!Ì <: Ë!Ì µ

´ T-SUB

¼

` Ü:輯 : Ë!Ì

So we can get away with not allowing instances of T-SUB as the final rule in the right-hand premise of an instance of T-ABS. Similarly, any derivation of the form . . . .

.

Ì <: Ë Ë <: Ì

½ ¾ ¾

. ½ µ

´ S-ARROW .

Ë !Ë <: Ì !Ì ` Ø : Ë !Ë

½ ¾ ½ ¾ ½ ¾

½ . µ

´ T-SUB

` Ø : Ì ` Ø : Ì !Ì

¾ ½ ½ ½ ¾

` Ø Ø : Ì

½ ¾ ¾ can be replaced by one of the form: . . . .

.

` Ø : Ì Ì <: Ë

½ ½ ½

. ¾ µ

´ T-SUB .

` Ø : Ë !Ë ` Ø : Ë

½ ½ ¾ ½

¾ . µ

´ T-APP

Ë <: Ì ` Ø Ø : Ë

¾ ¾ ½ ¾ ¾ µ

´ T-SUB

` Ø Ø : Ì

½ ¾ ¾ January 15, 2000 13. SUBTYPING 94

That is, we can take any derivation where subsumption is used as the final rule in the left-hand premise of an instance of T-APP and replace it by a derivation with one instance of subsumption appearing at the end of the right-hand premise and another instance of subsumption appearing at the end of the whole derivation. Finally, adjacent uses of subsumption can be coalesced, in the sense that any derivation of the form . . . .

.

` Ø : Ë Ë <: Í

. µ

´ T-SUB

` Ø : Í Í <: Ì µ

´ T-SUB

` Ø : Ì can be rewritten: . . . .

.

<: Í Í <: Ì

. Ë µ

´ S-TRANS

Ë <: Ì ` Ø : Ë µ

´ T-SUB

` Ø : Ì

13.2.6 Exercise [Recommended]: Show that a similar rearrangement can be per-

formed on derivations in which T-SUB is used immediately before T-PROJ. ¾

A motivating intuition behind all of these transformations is that nothing is harmed by moving most uses of subsumption as late as possible in a typing deriva- tion, so that each subterm is given the smallest possible (or minimal) type at the outset and this small type is maintained until a point is reached (in the application rule) where a larger type is needed. This motivates the following definition:

13.2.7 Definition: The algorithmic typing relation is the least relation closed un-

der the following rules:

fg <:

Algorithmic typing !

Á

` Ø : Ì

Algorithmic typing ( )

Ü:Ì ¾

(TA-VAR)

Á

` Ü : Ì

Á

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(TA-ABS)

Á

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

Á Á Á

` Ø : Ì Ì = Ì !Ì ` Ø : Ì ` Ì <: Ì

½ ½ ½ ½½ ½¾ ¾ ¾ ¾ ½½

(TA-APP)

Á

` Ø Ø : Ì

½ ¾ ½¾

January 15, 2000 13. SUBTYPING 95

Á

i ` Ø : Ì i for each i

(TA-RCD)

Á

` ßÐ =Ø ºººÐ =Ø } : ßÐ :Ì ºººÐ :Ì }

½ ½ Ò Ò ½ ½ Ò Ò

Á

` Ø : ßÐ :Ì ºººÐ :Ì }

½ ½ Ò Ò

(TA-PROJ)

Á

` غР: Ì

i i ¾

13.2.8 Exercise [Recommended]: Show, by example, that minimal types of terms

£

Ø ! Ö

in this calculus can decrease during evaluation. Give a term Ø such that

<: Ì Ì 6<: Ê Ê Ö Ì

and Ê but , where is the minimal type of and is the minimal type ¾ of Ø.

We now want to see formally that the algorithmic typing rules define the same relation as the ordinary rules. We do this in two steps: Soundness: Every typing statement that can be proved by an algorith- mic derivation can also be proved by an ordinary derivation. Completeness: Every typing statement that can be proved by an ordi- nary derivation can almost be proved by an algorithmic derivation.

(In fact, the algorithmic derivation may yield a better type.)

Á

` Ø : Ì

13.2.9 Theorem [Soundness of the algorithmic typing relation]: If , then

` Ø : Ì ¾ .

Proof: By straightforward induction on algorithmic typing derivations. The de-

tails are left as an exercise. ¾

The ordinary typing relation can be used to assign many types to a term, while the algorithmic typing relation assigns at most one (this is easy to check). So a

straightforward converse of Theorem 13.2.9 is clearly not going to hold. Instead, Ì

we can show that if a term Ø has a type under the ordinary typing rules, then

Ë <: Ì it has a better type Ë under the algorithmic rules, in the sense that .In other words, the algorithmic rules assign each typeable term its smallest possible

(“minimal”) type.

Á

` Ø : Ì ` Ø : Ë Ë <: Ì ¾ 13.2.10 Theorem [Minimal Typing]: If , then for some .

Proof: Exercise (recommended). ¾

13.2.11 Exercise: If we dropped the function subtyping rule S-ARROW but kept the rest of the subtyping and typing rules the same, would we lose the minimal typing property? If not, prove it. If so, give an example of a term that would have

two incomparable types. ¾ January 15, 2000 13. SUBTYPING 96

13.2.12 Exercise [Recommended]: Add numbers and iteration to the algorithmic typing relation. Prove that your algorithmic rules are sound and complete for the

declarative system. ¾

The proof itself will be presented, of course — probably in the solutions chapter.

13.2.13 Exercise [Recommended]: Show how to extend the proof of preservation

for the simply typed lambda-calculus (7.4.11) to the system with subtyping. ¾

13.3 Implementation

ÐeØ Öec ×ÙbØÝÔe ØÝË ØÝÌ =

ØÝeÕÚ ØÝË ØÝÌ ||

ÑaØch ´ØÝ˸ØÝ̵ ÛiØh

´ÌÝAÖÖ´ØÝ˽¸ØÝ˾µ¸ÌÝAÖÖ´ØÝ̽ ¸ØÝ̾ µµ !

´×ÙbØÝÔe ØÝ̽ ØÝ˽µ ²² ´×ÙbØÝÔe ØÝ˾ ØÝ̾µ

| ´_¸ÌÝÌÓÔµ !

ØÖÙe

| ´ÌÝÊecÓÖd´f˵¸ ÌÝÊecÓÖd´f̵µ !

Äi×غfÓÖ_aÐÐ

´fÙÒ ´Ði¸ØÝÌiµ !

ØÖÝ ÐeØ ØÝËi = Äi×غa××Óc Ði fË iÒ

×ÙbØÝÔe ØÝËi ØÝÌi

ÛiØh ÆÓØ_fÓÙÒd ! faÐ×eµ

| _ !

faÐ×e

ÐeØ Öec ØÝÔeÓf cØÜ Ø =

ÑaØch Ø ÛiØh

ÌÑÎaÖ´fi¸i¸_µ !

geØØÝÔe fi cØÜ i

| ÌÑAb×´fi¸Ü¸ØÝ˸ؽµ !

ÐeØ cØܳ = addbiÒdiÒg cØÜ Ü ´ÎaÖBiÒd´ØÝ˵µ iÒ

ÐeØ ØÝÌ = ØÝÔeÓf cØܳ ؽ iÒ

ÌÝAÖÖ´ØÝ˸ ØÝ×hifØ ØÝÌ ´¹½µµ

| ÌÑAÔÔ´fi¸Ø½¸Ø¾µ !

ÐeØ ØÝ̽ = ØÝÔeÓf cØÜ Ø½ iÒ

ÐeØ ØÝ̾ = ØÝÔeÓf cØÜ Ø¾ iÒ

´ÑaØch ØÝ̽ ÛiØh

ÌÝAÖÖ´ØÝ̽½¸ØÝ̽¾µ !

if ×ÙbØÝÔe ØÝ̾ ØÝ̽½ ØheÒ ØÝ̽¾

eÐ×e eÖÖÓÖ fi "ÔaÖaÑeØeÖ ØÝÔe Ñi×ÑaØch"

| _ ! eÖÖÓÖ fi "aÖÖÓÛ ØÝÔe eÜÔecØed"µ

January 15, 2000 13. SUBTYPING 97

| ÌÑÊecÓÖd´fi¸ fieÐd×µ !

ÐeØ fieÐdØÝ× = Äi×غÑaÔ ´fÙÒ ´Ði¸Øiµ ! ´Ði¸ ØÝÔeÓf cØÜ Øiµµ fieÐd× iÒ

ÌÝÊecÓÖd´fieÐdØÝ×µ

| ÌÑÈÖÓj´fi¸ ؽ¸ е !

´ÑaØch ´ØÝÔeÓf cØÜ Ø½µ ÛiØh

ÌÝÊecÓÖd´fieÐdØÝ×µ !

´ØÖÝ Äi×غa××Óc Ð fieÐdØÝ×

ÛiØh ÆÓØ_fÓÙÒd ! eÖÖÓÖ fi ´"ÐabeÐ "^Ð^" ÒÓØ ÔÖe×eÒØ"µµ

| _ ! eÖÖÓÖ fi "EÜÔecØed ÖecÓÖd ØÝÔe"µ

13.4 Meets and Joins

Ë Ì

A type  is called a join of a pair of types and if

` Ë <: Â

` Ì <: Â

` Ë <: Í ` Ì <: Í ` Â <: Í:

for all types Í,if and then Ì

A given typed lambda-calculus is said to have joins if, for every Ë and , there is

Ë Ì

some  that is a join of and under .

Ë Ì

Similarly, a type Å is called a meet of and if

` Å <: Ë

` Å <: Ì

` Ä <: Ë ` Ä <: Ì ` Ä <: Å:

for all types Ä,if and then

Ì Ä

A pair of types Ë and is said to be bounded below if there is some type such

Ä <: Ë ` Ä <: Ì

that ` and . A typed lambda-calculus is said to have bounded

Ì Ë Ì Å

meets if, for every Ë and such that and are bounded below, there is some Ì

that is a meet of Ë and .

ÐeØ Öec jÓiÒ ØÝË ØÝÌ =

if ×ÙbØÝÔe ØÝË ØÝÌ ØheÒ ØÝÌ

eÐ×e if ×ÙbØÝÔe ØÝÌ ØÝË ØheÒ ØÝË

eÐ×e ÑaØch ´ØÝ˸ØÝ̵ ÛiØh

´ÌÝÊecÓÖd´f½µ¸ ÌÝÊecÓÖd´f¾µµ !

ÐeØ Öec ÐÓÓÔ = fÙÒcØiÓÒ

´_¸[]µ ! []

| ´[]¸_µ ! []

| ´´Ð½¸Ø½µ::Öe×ؽ¸´Ð¾¸Ø¾µ::Öe× Ø¾µ !

if н = о ØheÒ

´Ð½¸´jÓiÒ Ø½ ؾµµ::´ÐÓÓÔ ´Öe×ؽ¸Öe×ؾµµ

eÐ×e []

iÒ ÐeØ f = ÐÓÓÔ ´f½¸f¾µ

January 15, 2000 13. SUBTYPING 98

iÒ ´ÑaØch f ÛiØh

´¶ ÛheÒ Øhe fiÖ×Ø fieÐd ÒaÑe× did ÒÓØ agÖee ¶µ

[] ! ÌÝÌÓÔ

| _ ! ÌÝÊecÓÖd´fµµ

| ´ÌÝAÖÖ´ØÝ˽¸ØÝ˾µ¸ÌÝAÖÖ´ØÝ̽¸Ø Ý̾µ µ !

´ØÖÝ ÌÝAÖÖ´ÑeeØ ØÝ˽ ØÝ̽¸ jÓiÒ ØÝ˾ ØÝ̾µ

ÛiØh ÆÓØ_fÓÙÒd ! ÌÝÌÓÔµ

| _ ! ÌÝÌÓÔ

aÒd ÑeeØ ØÝË ØÝÌ =

if ×ÙbØÝÔe ØÝË ØÝÌ ØheÒ ØÝË

eÐ×e if ×ÙbØÝÔe ØÝÌ ØÝË ØheÒ ØÝÌ

eÐ×e

ÑaØch ´ØÝ˸ØÝ̵ ÛiØh

´ÌÝÊecÓÖd´f½µ¸ ÌÝÊecÓÖd´f¾µµ !

ÐeØ Öec ÐÓÓÔ = fÙÒcØiÓÒ

´Öe×Øf½¸[]µ ! Öe×Øf½

| ´[]¸Öe×Øf¾µ ! Öe×Øf¾

| ´´Ð½¸Ø½µ::Öe×ؽ¸´Ð¾¸Ø¾µ::Öe× Ø¾µ !

if н = о ØheÒ

´Ð½¸´ÑeeØ Ø½ ؾµµ::´ÐÓÓÔ ´Öe×ؽ¸Öe×ؾµµ

eÐ×e Öai×e ÆÓØ_fÓÙÒd

iÒ ÐeØ f = ÐÓÓÔ ´f½¸f¾µ

iÒ ÌÝÊecÓÖd´fµ

| ´ÌÝAÖÖ´ØÝ˽¸ØÝ˾µ¸ÌÝAÖÖ´ØÝ̽¸Ø Ý̾µ µ !

ÌÝAÖÖ´jÓiÒ ØÝ˽ ØÝ̽¸ ÑeeØ ØÝ˾ ØÝ̾µ

| _ ! Öai×e ÆÓØ_fÓÙÒd

ÐeØ Öec ØÝÔeÓf³ cØÜ Ø =

ÑaØch Ø ÛiØh

ººº

| ÌÑÌÖÙe´fiµ !

ÌÝBÓÓÐ

| ÌÑFaÐ×e´fiµ !

ÌÝBÓÓÐ

| ÌÑÁf´fi¸×½¸×¾¸×¿µ !

if ×ÙbØÝÔe ´ØÝÔeÓf cØÜ ×½µ ÌÝBÓÓÐ ØheÒ

jÓiÒ ´ØÝÔeÓf cØÜ ×¾µ ´ØÝÔeÓf cØÜ ×¿µ

eÐ×e eÖÖÓÖ fi "gÙaÖd Óf cÓÒdiØiÓÒaÐ ÒÓØ a bÓÓÐeaÒ"

aÒd ØÝÔeÓf cØÜ Ø =

if !debÙgØÝÔeÓf ØheÒ

ËÙÔÔÓÖغDebÙgºÛÖaÔ "ØÝÔeÓf"

´fÙÒ ´µ ! ØÝÔeÓf³ cØÜ Øµ

´fÙÒ ´µ ! ÔÖØÑ cØÜ Øµ

´fÙÒ ØÝÌ ! ÔÖØÝ ØÝ̵ eÐ×e

January 15, 2000 13. SUBTYPING 99

ØÝÔeÓf³ cØÜ Ø

13.4.1 Exercise [Recommended]: Add booleans and conditionals to both the declar- ative typing relation and the algorithmic typing relation. Prove that your algorith-

mic rules are sound and complete for the declarative system. ¾

13.4.2 Exercise [Recommended]: The directory ×iÑÔÐeÔÐÙ× in the course web site contains an ML checker for the simply typed lambda-calculus with records, num-

bers, and booleans. Add subtyping (and a ÌÓÔ type) to this checker using the

algorithms described in this chapter. ¾

13.5 Primitive Subtyping 13.6 The Bottom Type 13.7 Other stuff Chapter 14

Imperative Objects

This chapter needs a little more writing, but my main annoyance with it is that the final section (on “self”) requires lazy evaluation at the moment. There are some fairly deep issues here (Didier and I have been discussing for years whether it is actually possible to build a completely satisfactory object model by translation to lambda-calculus, and this is one of the biggest reasons). I think the material is still valuable even so, but I’d love to find a better way around this point. Some of the examples in this chapter would look nicer if we added operations for record extension and overriding (not polymorphic: just on ordinary records). The overriding operation should, if possible, be consistent with the polymorphic record update operation.

In this chapter we come to our first substantial programming examples. We’ll use the features we have defined – functions, records, effects, fixed points, refer- ence cells, and subtyping – to give a straightforward model of objects and classes, as they are found in object-oriented languages such as and Java. We be- gin with very simple “stand-alone” objects and then proceed to define increasingly powerful kinds of classes.

14.1 Objects

An object is a encapsulating some internal state and offering access to this state to clients via a collection of methods. The internal state is typically broken up into a number of mutable instance variables (or fields) that are shared among the definitions of the methods (and typically inaccessible to the rest of the program). An object’s methods are invoked by the operation of message-sending. Our running example for the chapter will be simple “storage cell” objects. Each

cell object will hold a single number and respond to three messages: geØ, which

causes it to return the number it currently has; ×eØ, which sets its internal state

100 January 15, 2000 14. IMPERATIVE OBJECTS 101

to some number given by the sender of the message; and iÒc, which causes it to

increment the number it is holding. (Except for the iÒc message, our cells are just

an object-oriented variation of the Öefs that we saw in Chapter 9.) A very simple way of obtaining this behavior using the features we have stud- ied so far is to use a reference cell for the object’s internal state and a record of

functions for the methods.

c =

ÐeØ Ö = Öef ¼ iÒ

ßgeØ = _:ÍÒiغ !Ö¸

×eØ = i:Æaغ Ö:=i¸

iÒc = _:ÍÒiغ Ö:=×Ùcc´!Öµ};

Á

c : ßgeØ:ÍÒiØ! Æaظ ×eØ:ÆaØ! ÍÒiظ iÒc:ÍÒiØ! ÍÒiØ}

The fact that the state is shared by the methods and inaccessible to the rest of the

program arises directly from the lexical scope of the variable Ö. “Sending a mes-

sage” to the object c means just extracting some field of the record and applying it

to an appropriate argument. For example:

cº×eØ ¾;

cºiÒc ÙÒiØ;

cºgeØ ÙÒiØ;

´cº×eØ ¾; cºiÒc ÙÒiØ; cºgeØ ÙÒiص;

Á

ÙÒiØ : ÍÒiØ

ÙÒiØ : ÍÒiØ

¿ : ÆaØ

¿ : ÆaØ

Note the use of the syntactic sugar for sequencing (cf. Section ??) in the last line.

We could equivalently (but less readably) have written

ÐeØ Ü = cº×eØ ¾ iÒ ÐeØ Ý = cºiÒc ÙÒiØ iÒ cºgeØ ÙÒiØ;

or even (using the _ convention for “don’t care” variable names):

ÐeØ _ = cº×eØ ¾ iÒ ÐeØ _ = cºiÒc ÙÒiØ iÒ cºgeØ ÙÒiØ;

We may want to create and manipulate a lot of counters, so it will be convenient

to use an abbreviation for their rather long record type:

CÓÙÒØeÖ = ßgeØ:ÍÒiØ! Æaظ ×eØ:ÆaØ! ÍÒiظ iÒc:ÍÒiØ! ÍÒiØ};

To force the typechecker to print the type of a new counter using the short form

Ø a× Ì

CÓÙÒØeÖ, we add an explicit coercion (recall from Section ?? that means the

Ü:ÌºÜµØ same as ´ ):

January 15, 2000 14. IMPERATIVE OBJECTS 102

c =

ÐeØ Ö = Öef ¼ iÒ

ßgeØ = _:ÍÒiغ !Ö¸

×eØ = i:Æaغ Ö:=i¸

iÒc = _:ÍÒiغ Ö:=×Ùcc´!Öµ}

a× CÓÙÒØeÖ;

Á

c : CÓÙÒØeÖ

(This need to explicitly annotate terms to control the way their types are printed is a little annoying. It is the price we pay for “unbundling” all the features of our programming language into the simplest and most orthogonal possible units, so that we can study them in isolation. A practical high-level programming language design would probably combine many of these primitive features into more con- venient -constructs.) A typical piece of “client code” that manipulates counter objects might look

something like this:

iÒc¿ = c:CÓÙÒØeÖº ´cºiÒc ÙÒiØ; cºiÒc ÙÒiØ; cºiÒc ÙÒiص;

Á

iÒc¿ : CÓÙÒØeÖ ! ÍÒiØ

The function iÒc¿ takes a counter object and increments it three times by sending

it three iÒc messages in succession.

´cº×eØ 5; iÒc¿ c; cºgeØ ÙÒiص;

Á

8 : ÆaØ

14.2 Object Generators

In the development that follows, it will be useful to be able to manipulate all the instance variables of an object as a single unit. To support this, let us change the internal representation of our counters to be a record of reference cells and use the

name of this record to refer to instance variables from the method body.

c =

ÐeØ Ö = ßÜ=Öef ¼} iÒ

ßgeØ = _:ÍÒiغ !´ÖºÜµ¸

×eØ = i:Æaغ ÖºÜ:=i¸

iÒc = _:ÍÒiغ ÖºÜ:=×Ùcc´!´ÖºÜµµ}

a× CÓÙÒØeÖ;

Á

c : CÓÙÒØeÖ

This representation makes it is easy, for example, to write a counter generator that creates a new counter every time it is called.

January 15, 2000 14. IMPERATIVE OBJECTS 103

ÒeÛCÓÙÒØeÖ =

_:ÍÒiغ

´ÐeØ Ö = ßÜ=Öef ¼} iÒ

ßgeØ = _:ÍÒiغ !´ÖºÜµ¸

×eØ = i:Æaغ ÖºÜ:=i¸

iÒc = _:ÍÒiغ ÖºÜ:=×Ùcc´!´ÖºÜµµ}

a× CÓÙÒØeÖµ;

Á

ÒeÛCÓÙÒØeÖ : ÍÒiØ ! CÓÙÒØeÖ

14.3 Subtyping

One of the reasons for the popularity of object-oriented programming styles is that they permit objects of many shapes to be manipulated by the same client code.

For example, suppose that, in addition to the CÓÙÒØeÖ objects defined above, we also create some cell objects with one more method that allows them to be reset

to their initial state (say, ¼) at any time.

Êe×eØCÓÙÒØeÖ = ßgeØ:ÍÒiØ! Æaظ

×eØ:ÆaØ! ÍÒiظ

iÒc:ÍÒiØ! ÍÒiظ

Öe×eØ:ÍÒiØ! ÍÒiØ};

ÒeÛÊe×eØCÓÙÒØeÖ =

_:ÍÒiغ

ÐeØ Ö = ßÜ=Öef ¼} iÒ

ßgeØ = _:ÍÒiغ !´ÖºÜµ¸

×eØ = i:Æaغ ÖºÜ:=i¸

iÒc = _:ÍÒiغ ÖºÜ:=×Ùcc´!´ÖºÜµµ¸

Öe×eØ = _:ÍÒiغ ÖºÜ:=¼}

a× Êe×eØCÓÙÒØeÖ;

Á

ÒeÛÊe×eØCÓÙÒØeÖ : ÍÒiØ ! Êe×eØCÓÙÒØeÖ

Note that our old iÒc¿ function on counters can safely use our refined counters

too:

Öc = ÒeÛÊe×eØCÓÙÒØeÖ ÙÒiØ;

´iÒc¿ Öc; ÖcºÖe×eØ ÙÒiØ; iÒc¿ Öc; ÖcºgeØ ÙÒiص;

Á

Öc : Êe×eØCÓÙÒØeÖ

¿ : ÆaØ January 15, 2000 14. IMPERATIVE OBJECTS 104

14.4 Basic classes ÒeÛÊe×eØCÓÙÒØeÖ The definitions of ÒeÛCÓÙÒØeÖ and are identical except for the

body of the Öe×eØ method. Of course, for such short definitions this makes little difference, but if the method bodies were much longer we might quickly find our- selves wanting to write the common ones in just one place. The mechanism by

which this is achieved in most object-oriented languages is called the class. ÒeÛCÓÙÒØeÖ

Here is one very simple way to define ÒeÛÊe×eØCÓÙÒØeÖ in terms of :

ÒeÛÊe×eØCÓÙÒØeÖ =

_:ÍÒiغ

´ÐeØ c = ÒeÛCÓÙÒØeÖ ÙÒiØ iÒ

ßgeØ = cºgeظ

×eØ = cº×eظ

iÒc = cºiÒc¸

Öe×eØ = _:ÍÒiغ cº×eØ ¼}

a× Êe×eØCÓÙÒØeÖµ;

Á

ÒeÛÊe×eØCÓÙÒØeÖ : ÍÒiØ ! Êe×eØCÓÙÒØeÖ geØ

But this trick is not very robust. For example, if the type CÓÙÒØeÖ had just and

×eØ ÒeÛÊe×eØCÓÙÒØeÖ iÒc methods (no ), then we couldn’t write in this way. A more general approach is to abstract the methods of a prototype counter

object over the instance variables. This is a simple example of a class.

CÓÙÒØeÖÊeÔ = ßÜ: Êef ÆaØ};

cÓÙÒØeÖCÐa×× =

Ö:CÓÙÒØeÖÊeÔº

´ßgeØ = _:ÍÒiغ !´ÖºÜµ¸

×eØ = i:Æaغ ÖºÜ:=i¸

iÒc = _:ÍÒiغ ÖºÜ:=×Ùcc´!´ÖºÜµµ}

a× CÓÙÒØeÖµ;

Á

cÓÙÒØeÖCÐa×× : CÓÙÒØeÖÊeÔ ! CÓÙÒØeÖ cÓÙÒØeÖCÐa××

Now we can build a class for Êe×eØCÓÙÒØeÖ by re-using the fields of :

Öe×eØCÓÙÒØeÖCÐa×× =

Ö:CÓÙÒØeÖÊeÔº

ÐeØ ×ÙÔeÖ = cÓÙÒØeÖCÐa×× Ö iÒ

´ßgeØ = ×ÙÔeÖºgeظ

×eØ = ×ÙÔeÖº×eظ

iÒc = ×ÙÔeÖºiÒc¸

Öe×eØ = _:ÍÒiغ ÖºÜ:=¼}

a× Êe×eØCÓÙÒØeÖµ;

Á

Öe×eØCÓÙÒØeÖCÐa×× : CÓÙÒØeÖÊeÔ ! Êe×eØCÓÙÒØeÖ ÒeÛÊe×eØCÓÙÒØeÖ

The definitions of ÒeÛCÓÙÒØeÖ and become trivial: we simply Öe×eØCÓÙÒØeÖCÐa×× allocate the instance variables and supply them to cÓÙÒØeÖCÐa×× or , where the real work happens:

January 15, 2000 14. IMPERATIVE OBJECTS 105

ÒeÛCÓÙÒØeÖ =

_:ÍÒiغ

´ÐeØ Ö = ßÜ=Öef ¼} iÒ

cÓÙÒØeÖCÐa×× Öµ

a× CÓÙÒØeÖ;

ÒeÛÊe×eØCÓÙÒØeÖ =

_:ÍÒiغ

´ÐeØ Ö = ßÜ=Öef ¼} iÒ

Öe×eØCÓÙÒØeÖCÐa×× Öµ

a× Êe×eØCÓÙÒØeÖ;

Á

ÒeÛCÓÙÒØeÖ : ÍÒiØ ! CÓÙÒØeÖ

ÒeÛÊe×eØCÓÙÒØeÖ : ÍÒiØ ! Êe×eØCÓÙÒØeÖ

14.5 Extending the Internal State

Suppose we want to define a class of BackÙÔCÓÙÒØeÖs whose reset method resets

their state to its value at the last call to a new method backup...

BackÙÔCÓÙÒØeÖ = ßgeØ:ÍÒiØ! Æaظ

×eØ:ÆaØ! ÍÒiظ

iÒc:ÍÒiØ! ÍÒiظ

Öe×eØ:ÍÒiØ! ÍÒiظ

backÙÔ: ÍÒiØ! ÍÒiØ};

BackÙÔCÓÙÒØeÖÊeÔ = ßÜ: Êef Æaظ b: Êef ÆaØ};

Here is the class:

backÙÔCÓÙÒØeÖCÐa×× =

Ö:BackÙÔCÓÙÒØeÖÊeÔº

´ßgeØ = _:ÍÒiغ !´ÖºÜµ¸

×eØ = i:Æaغ ÖºÜ:=i¸

iÒc = _:ÍÒiغ ÖºÜ:=×Ùcc´!´ÖºÜµµ¸

Öe×eØ = _:ÍÒiغ ÖºÜ:=!´Öºbµ¸

backÙÔ = _:ÍÒiغ Öºb:=!´ÖºÜµ}

a× BackÙÔCÓÙÒØeÖµ;

Á

backÙÔCÓÙÒØeÖCÐa×× : BackÙÔCÓÙÒØeÖÊeÔ ! BackÙÔCÓÙÒØeÖ a×× The interesting point is that we can actually define backÙÔCÓÙÒØeÖCÐ in

terms of Öe×eØCÓÙÒØeÖCÐa××. Note how subtyping is used in checking the defi- Öe×eØ nition of ×ÙÔeÖ. Also, note that we need to override the definition of the

method as well as adding backÙÔ.

backÙÔCÓÙÒØeÖCÐa×× =

Ö:BackÙÔCÓÙÒØeÖÊeÔº

ÐeØ ×ÙÔeÖ = Öe×eØCÓÙÒØeÖCÐa×× Ö iÒ

´ßgeØ = ×ÙÔeÖºgeظ

January 15, 2000 14. IMPERATIVE OBJECTS 106

×eØ = ×ÙÔeÖº×eظ

iÒc = ×ÙÔeÖºiÒc¸

Öe×eØ = _:ÍÒiغ ÖºÜ:=!´Öºbµ¸

backÙÔ = _:ÍÒiغ Öºb:=!´ÖºÜµ}

a× BackÙÔCÓÙÒØeÖµ;

Á

backÙÔCÓÙÒØeÖCÐa×× : BackÙÔCÓÙÒØeÖÊeÔ ! BackÙÔCÓÙÒØeÖ

The variable ×ÙÔeÖ was used above to “copy functionality” from the superclass into the new subclass.

The ×ÙÔeÖ variable can also be used inside method definitions to extend the

superclass’s behavior with something new. Suppose, for instance, that we want a iÒc variant of our backÙÔCÓÙÒØeÖ class in which the method increments not only

the cell’s value but also the backed-up value in the instance variable b. (Goodness

knows why this behavior would be useful—it’s just an example!)

fÙÒÒÝBackÙÔCÓÙÒØeÖCÐa×× =

Ö:BackÙÔCÓÙÒØeÖÊeÔº

ÐeØ ×ÙÔeÖ = Öe×eØCÓÙÒØeÖCÐa×× Ö iÒ

´ßgeØ = ×ÙÔeÖºgeظ

×eØ = ×ÙÔeÖº×eظ

iÒc = _:ÍÒiغ

´×ÙÔeÖºiÒc ÙÒiØ;

Öºb := ×Ùcc´!´Öºbµµµ¸

Öe×eØ = _:ÍÒiغ ÖºÜ:=!´Öºbµ¸

backÙÔ = _:ÍÒiغ Öºb:=!´ÖºÜµ}

a× BackÙÔCÓÙÒØeÖµ;

Á

fÙÒÒÝBackÙÔCÓÙÒØeÖCÐa×× : BackÙÔCÓÙÒØeÖÊeÔ ! BackÙÔCÓÙÒØeÖ iÒc Note how use of ×ÙÔeÖºiÒc in the definition of avoids repeating the super-

class’s iÒc code here.

14.6 Classes with “Self”

Our final extension is allowing the methods of classes to refer to each other “re- cursively.” For example, suppose that we want to implement the inc method of simple counters in terms of the get and set methods. (Of course, all three methods are so small in this example that all this code reuse is hardly worth the trouble! For larger examples, though, it can make a substantial difference in code size and

maintainability.)

cÓÙÒØeÖCÐa×× =

Ö:CÓÙÒØeÖÊeÔº

fiÜ

´×eÐf: CÓÙÒØeÖº

ßgeØ = _:ÍÒiغ !´ÖºÜµ¸

×eØ = i:Æaغ ÖºÜ:=i¸

iÒc = _:ÍÒiغ ×eÐfº×eØ ´×Ùcc´×eÐfºgeØ ÙÒiصµ}µ;

January 15, 2000 14. IMPERATIVE OBJECTS 107

Á

cÓÙÒØeÖCÐa×× : CÓÙÒØeÖÊeÔ ! ßgeØ:ÍÒiØ! Æaظ ×eØ:ÆaØ! ÍÒiظ iÒc:ÍÒiØ! ÍÒiØ}

Classes in mainstream object-oriented languages such as Smalltalk, C++, and Java actually support a more general form of recursive call between methods, sometimes known as open recursion. Instead of taking the fixed point within the

class, we wait until we use the class to actually create an object.

cÓÙÒØeÖCÐa×× =

Ö:CÓÙÒØeÖÊeÔº

×eÐf: CÓÙÒØeÖº

ßgeØ = _:ÍÒiغ !´ÖºÜµ¸

×eØ = i:Æaغ ÖºÜ:=i¸

iÒc = _:ÍÒiغ ×eÐfº×eØ ´×Ùcc´×eÐfºgeØ ÙÒiصµ};

Á

cÓÙÒØeÖCÐa×× : CÓÙÒØeÖÊeÔ !

CÓÙÒØeÖ ! ßgeØ:ÍÒiØ! Æaظ ×eØ:ÆaØ! ÍÒiظ iÒc:ÍÒiØ! ÍÒiØ}

ÒeÛCÓÙÒØeÖ =

_:ÍÒiغ

ÐeØ Ö = ßÜ=Öef ¼} iÒ

fiÜ ´cÓÙÒØeÖCÐa×× Öµ;

Á

ÒeÛCÓÙÒØeÖ : ÍÒiØ ! ßgeØ:ÍÒiØ! Æaظ ×eØ:ÆaØ! ÍÒiظ iÒc:ÍÒiØ! ÍÒiØ}

What’s interesting about leaving the recursion open is that, when we build a cÓÙÒØeÖCÐa×× new class by subclassing cÓÙÒØeÖCÐa××, we can override the methods of

in such a way that recursive calls to these methods from within cÓÙÒØeÖCÐa×× will actually invoke the new method bodies that we provide. For example, here’s a

subclass that keeps track of how many times the geØ method has been called.

ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ = ßgeØ:ÍÒiØ! Æaظ

×eØ:ÆaØ! ÍÒiظ

iÒc:ÍÒiØ! ÍÒiظ

acce××e×:ÍÒiØ! ÆaØ};

ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖÊeÔ = ßÜ: Êef Æaظ a: Êef ÆaØ};

iÒ×ØÖÙÑeÒØedCÓÙÒØeÖCÐa×× =

Ö:ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖÊeÔº

×eÐf: ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖº

ÐaÞÝ ÐeØ ×ÙÔeÖ = cÓÙÒØeÖCÐa×× Ö ×eÐf iÒ

ÐaÞÝ

ßgeØ = _:ÍÒiغ

ÐeØ Öe×ÙÐØ = ×ÙÔeÖºgeØ ÙÒiØ iÒ

´Öºa:=×Ùcc´!´Öºaµµ; Öe×ÙÐص¸

×eØ = ×ÙÔeÖº×eظ

iÒc = ×ÙÔeÖºiÒc¸

acce××e× = _:ÍÒiغ !´Öºaµ}

a× ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ;

Á

iÒ×ØÖÙÑeÒØedCÓÙÒØeÖCÐa×× : ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖÊeÔ !

ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ ! ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ

January 15, 2000 14. IMPERATIVE OBJECTS 108 geØ Notice that, because of the open recursion through ×eÐf, the call to from

within iÒc results in the a field being incremented, even though the increment- geØ ing behavior of geØ is defined in the subclass and the call to appears in the

superclass.

ÒeÛÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ 14.6.1 Exercise: The two ÐaÞÝ annotations in are both

essential. Check what happens when either of them is omitted. ¾

We create an instrumented counter in the same way as before—by taking a fixed point of the class and providing it with some newly allocated instance vari-

ables.

ÒeÛÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ =

_:ÍÒiغ

ÐeØ Ö = ßÜ = Öef ¼¸ a = Öef ¼} iÒ

fiÜ ´iÒ×ØÖÙÑeÒØedCÓÙÒØeÖCÐa×× Öµ;

Á

ÒeÛÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ : ÍÒiØ ! ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ

geØ iÒc

Note how the acce××e× method counts calls to both and :

ic = ÒeÛÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖ ÙÒiØ;

icºgeØ ÙÒiØ;

Á

¼ : ÆaØ

icºacce××e× ÙÒiØ;

Á

½ : ÆaØ

icºiÒc ÙÒiØ;

Á

ÙÒiØ : ÍÒiØ

icºgeØ ÙÒiØ;

Á

½ : ÆaØ

icºacce××e× ÙÒiØ;

Á

¿ : ÆaØ

14.6.2 Exercise [Recommended]: Use the fÙÐÐ×Ùbeff checker from the course di-

rectory to implement the following extensions to the classes above:

ØeÖCÐa×× 1. Change the definition of iÒ×ØÖÙÑeÒØedCÓÙÒ so that it also counts

calls to ×eØ.

ØeÖCÐa×× 2. Extend your modified iÒ×ØÖÙÑeÒØedCÓÙÒ with a subclass that adds

a Öe×eØ method (as in Section 14.3). 3. Extend this subclass with yet another subclass that supports backups as well

(as in Section 14.5). ¾ Chapter 15

Recursive Types

the type IntList is an infinite tree

so let’s just allow types to be infinite; use the  notation as a shorthand for infinite trees (Of course, the typechecker can’t actually manipulate infinite trees; later in the

chapter we will see two different ways of dealing with  types more realistically)

15.1 Examples

Lists Hungry Functions As another simple illustration of the use of recursive types, here is a type of func-

tions that can accept any number of numeric arguments:

ÀÙÒgÖÝ = Aº ÆaØ ! A;

An element of this type can be defined using the least fixed point operator on

values:

f =

fiÜ

´f: ÆaØ!ÀÙÒgÖݺ

Ò:Æaغ

fµ;

Á

f : ÆaØ ! ÆaØ ! ÀÙÒgÖÝ

f ¼ ½ ¾ ¿ 4 5;

Á

´Ò:Æaغ fiÜ f³:ÆaØ! ÀÙÒgÖݺ Ò³:Æaغf³µ : Aº ÆaØ ! A

109 January 15, 2000 15. RECURSIVE TYPES 110

Recursive Values from Recursive Types A more challenging example—and one that reveals some of the power of the ex- tension we are making—uses recursive types to write down a well-typed version

of the least-fixed-point combinator:

fiÜÔÓiÒØ =

Ì

f:Ì! ̺

´Ü:´AºA! ̵º f ´Ü ܵµ

´Ü:´AºA! ̵º f ´Ü ܵµ;

Á

fiÜÔÓiÒØ : ´Ì!̵ ! Ì Ì

Untyped Lambda-Calculus, Redux Perhaps the best illustration of the power of recursive types is the observation that it is possible to embed the whole untyped lambda-calculus (in a well-typed

way!) into a statically typed calculus with recursive types. Let D be the following

universal type:

D = Xº X!X;

(Note that the form of D’s definition is reminiscent of the defining properties of

“universal domains” in denotational semantics.) Now define an “injection func-

D D D

tion” ÐaÑ mapping functions from to into elements of as follows:

ÐaÑ = f:D! Dº f;

Á

ÐaÑ : ´D! Dµ ! D ! D

aÔ = f:Dº a:Dº f a;

Á

aÔ : D ! D ! ´Xº X ! Xµ

Now, suppose Å is a closed pure lambda-term involving just variables, abstrac- Å

tions, and applications. Then we can construct an element of D representing , ?

written Å , in a uniform way as follows:

?

Ü = Ü

? ?

´ܺŵ = ÐaÑ ´Ü:Dº Å µ

? ? ?

´Å Ƶ = aÔ Å Æ

For example, here is how the untyped fixed point combinator is expressed as an

element of D:

fiÜD = ÐaÑ ´f:Dº

aÔ ´ÐaÑ ´Ü:Dº aÔ f ´aÔ Ü Üµµµ

´ÐaÑ ´Ü:Dº aÔ f ´aÔ Ü Üµµµµ;

Á

fiÜD : D ! D January 15, 2000 15. RECURSIVE TYPES 111

15.1.1 Exercise: Note that the term defining fiÜÔÓiÒØ contains many redices. Use

the reduction rules (C-UNFOLDFOLD plus the usual ¬-reduction rule) to find its

normal form. What is the type-erasure of this normal form? ¾

We can go even further, if we work in a language with variants as in Section 8.5. Then we can extend the datatype of pure lambda-terms to include numbers like

this:

D = Xº <ÒaØ:Æaظ fÒ:X! X>;

D D ÒaØ That is, an element of D is either a number or a function from to , tagged

or fÒ, repectively. It will also be convenient to have an abbreviation for the “once-

unrolled” body of D:

DBÓdÝ = <ÒaØ:Æaظ fÒ:D! D>;

The implementation of the ÐaÑ constructor is essentially the same as before:

ÐaÑ = f:D! Dº

a× DBÓdÝ;

Á

ÐaÑ : ´D! Dµ ! DBÓdÝ

The implementation of aÔ, though, is different in an interesting way:

aÔ =

f:Dº a:Dº

ca×e f Óf

ÒaØ=Ò µ diÚeÖge ÙÒiØ

D

| fÒ=f µ f a;

Á

aÔ : D ! D ! D

Notice how closely the tag-checking going on here resembles the run-time tag checking inside an implementation of a strongly-but-latently typed language such as Scheme [?]. In this sense, typed computation may be said to “include” untyped or dynamically typed computation. Similar tag checking is needed in order to de-

fine the successor function on elements of D:

×Ùc =

f:Dº

ca×e f Óf

ÒaØ=Ò µ ´<ÒaØ=×Ùcc Ò> a× DBÓdݵ

| fÒ=f µ diÚeÖge ÙÒiØ;

D D

The injection of ¼ into is trivial:

ÞÖÓ = <ÒaØ=¼> a× DBÓdÝ;

Á

×Ùc : D ! DBÓdÝ

ÞÖÓ : DBÓdÝ January 15, 2000 15. RECURSIVE TYPES 112

15.1.2 Exercise: Use the untyped fixed point combinator that we saw above to de- ¾ fine an untyped factorial function on D.

15.1.3 Exercise [Recommended]: Using the fÙÐÐÖec checker from the course web

directory, extend the datatype D to include untyped records

D = Xº <ÒaØ:Æaظ fÒ:X! X¸ Öcd:ÆaØ! X>; and implement record construction and field projection. For simplicity, use natu- ral numbers as field labels—i.e., records are represented as functions from natural

numbers to elements of D. (N.b.: this exercise has nothing to do with hungry func-

tions!) ¾

Recursive Objects

CÓÙÒØeÖ = Ⱥ ßgeØ:Æaظ iÒc:ÍÒiØ! È};

Ô =

ÐeØ cÖeaØe =

fiÜ

´cÖ: ßÜ:ÆaØ}! CÓÙÒØeÖº

×: ßÜ:ÆaØ}º

ßgeØ = ׺ܸ

iÒc = _:ÍÒiغ cÖ ßÜ=×Ùcc´×ºÜµ}}µ

cÖeaØe ßÜ=¼};

Á

Ô : ßgeØ:Æaظ iÒc:ÍÒiØ! CÓÙÒØeÖ}

Ô½ = ÔºiÒc ÙÒiØ;

Ô½ºgeØ;

Á

Ô½ : CÓÙÒØeÖ

½ : ÆaØ

15.2 Equi-recursive Types

note that we cannot obtain all infinite trees by writing finite expressions using , just the regular ones.

Prove this by writing a function that expands a  type into its regular tree form, and showing that this function is not surjective (maybe the latter is an exercise). introduce the idea of contractive types

¯ use the equivalence relation (should introduce it previously) to capture the intuition that a recursive type is “the same as” its unfolding

January 15, 2000 15. RECURSIVE TYPES 113

XºÌ!Ì!X

¯ but this doesn’t give us enough equivalences. For example and

!´XºÌ!Ì!Xµ Ì are equal as trees but inequivalent.

¯ So we switch to a coinductive view of equivalence.

¯ now equivalence coincides with equality of infinite tree expansions (prove it!)

¯ Now we need to decide this coinductive equivalence – show simulation algorithm (and its ML realization) – prove that it is sound, complete, and terminating

notice that we need to deal with more than just type equivalence: we also need

to provide an eÜÔÓ×e function that unrolls recursive types as needed during typ-

ing. What needs to be proved about this?

B 

Algorithmic rules for equi-recursive types !

Á

` Ë  Ì

Algorithmic type equivalence ( )

´Ë  ̵ ¾È

(QA-LOOP)

Á

È` Ë  Ì

Á

È ; ´XºË  ̵ ` fX 7! XºË gË  Ì

½ ½

½ (QA-RECL)

Á

È` XºË  Ì

½

Á

È ; ´Ë  XºÌ µ ` Ë  fX 7! XºÌ gÌ

½ ½

½ (QA-RECR)

Á

È` Ë  XºÌ

½

Á

` B  B

È (QA-BASE)

Á Á

È`Ë  Ì È`Ë  Ì

½ ¾ ¾

½ (QA-ARROW)

Á

È`Ë !Ë  Ì !Ì

½ ¾ ½ ¾

¼

Á

` Ì ¶ Ì

Exposure ( )

¼

Á

` fX 7! XºÌ gÌ ¶ Ì ½

½ (XA-REC)

¼

Á

` XºÌ ¶ Ì ½

Ì is not a recursive type

(XA-OTHER)

Á

` Ì ¶ Ì

Á

` Ø : Ì

Algorithmic typing ( )

Ü:Ì ¾

(TA-VAR)

Á

` Ü : Ì

January 15, 2000 15. RECURSIVE TYPES 114

Á

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(TA-ABS)

Á

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

Á Á Á Á

` Ø : Ì ` Ì ¶ Ì !Ì ` Ø : Ì ` Ì  Ì

½ ½ ½ ½½ ½¾ ¾ ¾ ¾ ½½

(TA-APP)

Á

` Ø Ø : Ì

½ ¾ ½¾

ML Implementation

Datatypes

ØÝÔe ØÝ =

ÌÝAÖÖ Óf ØÝ ¶ ØÝ

| ÌÝÁd Óf ×ØÖiÒg

| ÌÝÎaÖ Óf iÒØ ¶ iÒØ

| ÌÝÊec Óf ×ØÖiÒg ¶ ØÝ

ØÝÔe ØeÖÑ =

ÌÑÎaÖ Óf iÒfÓ ¶ iÒØ ¶ iÒØ

| ÌÑAb× Óf iÒfÓ ¶ ×ØÖiÒg ¶ ØÝ ¶ ØeÖÑ

| ÌÑAÔÔ Óf iÒfÓ ¶ ØeÖÑ ¶ ØeÖÑ

Type substitution

Type equivalence

ÐeØ Öec ØÝeÕÚ ÔaiÖ× cØÜ ØÝË ØÝÌ =

Äi×غÑeÑ ´ØÝ˸ØÝ̵ ÔaiÖ×

|| ÑaØch ´ØÝ˸ØÝ̵ ÛiØh

´ÌÝAÖÖ´ØÝ˽¸ØÝ˾µ¸ÌÝAÖÖ´ØÝ̽¸ ØÝ̾µ µ !

´ØÝeÕÚ ÔaiÖ× cØÜ ØÝ˽ ØÝ̽µ ²² ´ØÝeÕÚ ÔaiÖ× cØÜ ØÝ˾ ØÝ̾µ

| ´ÌÝÁd´b½µ¸ÌÝÁd´b¾µµ ! b½=b¾

| ´ÌÝÎaÖ´i¸_µ¸ÌÝÎaÖ´j¸_µµ ! i=j

| ´ÌÝÊec´Ü¸ØÝ˽µ¸_µ !

ØÝeÕÚ ´´ØÝ˸ØÝ̵::ÔaiÖ×µ cØÜ ´ØÝ×Ùb×Ø×ÒiÔ ØÝË ØÝ˽µ ØÝÌ

| ´_¸ÌÝÊec´Ü¸ØÝ̽µµ !

ØÝeÕÚ ´´ØÝ˸ØÝ̵::ÔaiÖ×µ cØÜ ØÝË ´ØÝ×Ùb×Ø×ÒiÔ ØÝÌ ØÝ̽µ

| _ ! faÐ×e

ÐeØ ØÝeÕÚ cØÜ ØÝË ØÝÌ =

ØÝeÕÚ [] cØÜ ØÝË ØÝÌ January 15, 2000 15. RECURSIVE TYPES 115

Typing

ÐeØ Öec ØÝÔeÓf cØÜ Ø =

ÑaØch Ø ÛiØh

ÌÑÎaÖ´fi¸i¸_µ !

geØØÝÔe fi cØÜ i

| ÌÑAb×´fi¸Ü¸ØÝ˸ؽµ !

ÐeØ cØܳ = addbiÒdiÒg cØÜ Ü ´ÎaÖBiÒd´ØÝ˵µ iÒ

ÐeØ ØÝÌ = ØÝÔeÓf cØܳ ؽ iÒ

ÌÝAÖÖ´ØÝ˸ ØÝ×hifØ ØÝÌ ´¹½µµ

| ÌÑAÔÔ´fi¸Ø½¸Ø¾µ !

ÐeØ ØÝ̽ = ØÝÔeÓf cØÜ Ø½ iÒ

ÐeØ ØÝ̾ = ØÝÔeÓf cØÜ Ø¾ iÒ

´ÑaØch ØÝ̽ ÛiØh

ÌÝAÖÖ´ØÝ̽½¸ØÝ̽¾µ !

if ØÝeÕÚ cØÜ ØÝ̾ ØÝ̽½ ØheÒ ØÝ̽¾

eÐ×e eÖÖÓÖ fi "ÔaÖaÑeØeÖ ØÝÔe Ñi×ÑaØch"

| _ ! eÖÖÓÖ fi "aÖÖÓÛ ØÝÔe eÜÔecØed"µ

15.3 Iso-recursive Types

A different, and even simpler, way of dealing with recursive types is to “make the

isomorphism explicit”...

! B   : Iso-recursive types

New syntactic forms

Ø ::= ... (terms...)

[Ì] Ø

fÓÐd folding

[Ì] Ø ÙÒfÓÐd unfolding

Ú ::= ... (values...)

[Ì] Ú fÓÐd folding

Ì ::= ... (types...)

X type variable XºÌ  recursive type

::= ... (contexts...) X

; type variable binding

¼

! Ø New evaluation rules (Ø )

January 15, 2000 15. RECURSIVE TYPES 116

ÙÒfÓÐd [Ë] ´fÓÐd [Ì] Ú µ ! Ú ½

½ (E-FOLDBETA)

¼

Ø ! Ø ½

½ (E-FOLD)

¼

fÓÐd [Ì] Ø ! fÓÐd [Ì] Ø

½

½

¼

Ø ! Ø ½

½ (E-UNFOLD)

¼

ÙÒfÓÐd [Ì] Ø ! ÙÒfÓÐd [Ì] Ø

½

½

` Ø : Ì

New typing rules ( )

Í = XºÌ ` Ø : fX 7! ÍgÌ

½ ½

½ (T-FOLD)

` fÓÐd [Í] Ø : Í

½

Í = XºÌ ` Ø : Í ½

½ (T-UNFOLD)

` ÙÒfÓÐd [Í] Ø : fX 7! ÍgÌ

½ ½

15.3.1 Exercise: Re-do the examples in Section 15.1 using the Using the fÙÐÐi×ÓÖec

checker from the course web directory. (Solution on page 260.) ¾

Prove: preservation and progress Nice exercise: observe that we can just erase folds and unfolds from a well- typed program to obtain a well-typed program in the equi-recursive system. This tells us that any well typed iso-recursive program is “meaningful.” Does this con- stitute “soundness”? (Answer: no, it doesn’t tell us that the fold and unfold typing rules were done properly.)

15.4 Subtyping and Recursive Types Chapter 16

Case Study: Featherweight Java

This chapter will draw some connections between the material that’s been presented so far and the mainstream world of object-oriented type systems, focusing on Java. The pedagog- ical vehicle will be the Featherweight Java language studied by Atsushi Igarashi, Phil Wadler, and myself [IPW99]. It is a very simple core calculus, not much larger than the lambda-calculus, omitting nearly all of the features of the full Java language (including assignment!), while retaining its basic flavor: classes, objects, methods, fields, (explicitly declared) subtyping, casts, etc. The presentation here will be based closely on (the full version of) the OOPSLA paper on FJ. The main technical work to be done lies in tying FJ as explicitly as possible with the concepts we have already seen. This is not all that simple, since we’ve been working in an entirely “structural” setting, where the only salient thing about a type expression is its structure (i.e., there are no “type names” except as simple abbreviations for structures), while Java uses names throughout its type system. A section re-formulating the simply typed lambda-calculus with subtyping in “by-name form” should provide a helpful bridge.

Sections:

¯ By-name vs. structural presentations of type systems (note a big advantage of struc- tural presentations: portability! If you’re going to transmit code across the network, then what do the names mean??)

¯ A by-name presentation of the simply typed lambda-calculus with subtyping (Comments about Pascal vs. M3 treatments of “branding”.)

¯ Summary of Featherweight Java

117 Chapter 17

Type Reconstruction

For technical reasons, this chapter uses a slightly different definition of substitution from what we had before. This should be changed to correspond exactly to the earlier notion. Aside from that, it’s essentially finished. The present chapter does not mention let-polymorphism. I think that’s a shame and I’ve tried to figure out how to put in something about it, but it’s apparently quite hard to do it in a rigorous way without going on for page after page of technicalities.

Given an explicitly typed term in the simply typed lambda-calculus, we have seen an algorithm for determining its type, if it has one. In this chapter, we develop a more powerful type reconstruction algorithm, capable of calculating a principal type for a term in which some of the explicit type annotations are replaced by variables. Similar algorithms lie at the heart of languages like ML and Haskell. The term “type inference” is often used instead of “type reconstruction.”

17.1 Substitution

!Æ X We will work in this chapter with the system  , the simply typed lambda calculus with numbers and an infinite collection of atomic types. When we saw them in Section 8.1, these atomic types were completely uninterpreted. Now we are going to think of them as type variables—i.e., placeholders standing for other types. In order to make this idea precise, we need to define what it means to substitute arbitrary types for type variables.

17.1.1 Definition: A type substitution (or, for purposes of this chapter, just sub-

stitution) is a finite function from type variables to types. For example, we write

X 7! Ì; Y 7! Íg X Ì Y Í f for the substitution that maps to and to and is undefined on other arguments.

118 January 15, 2000 17. TYPE RECONSTRUCTION 119

We can regard a substitution  as a function from types to types in an obvious

way:

¬

 X Ì

Ì if maps to

X =

X 

X if is not in the domain of

´Æaص = ÆaØ

´Ì !Ì µ = Ì ! Ì

½ ¾ ½ ¾ Note that we do not need to make any special provisions to avoid variable capture during type substitution, because there are no binders for type variables. (This will change when we discuss System F in Chapter 18; we will then have to treat type

substitutions more carefully.)

 µ´Üµ ´ ´Üµµ

Substitution is extended to contexts by defining ´ to be . Similarly, Ø

a type substitution is applied to a term Ø by applying it to all types appearing in .

­  Æ ­

If  and are type substitutions, we write for the type substitution formed ­

by composing  and as follows:

8

´­´Xµµ X ¾ ´­µ

< if dom

X ¾= ´­µ X ¾ ´µ ´Xµ

 Æ ­µ´Xµ=

´ if dom and dom

:

¾= ´­µ [ ´µ :

undefined if X dom dom

 Æ ­µÌ = ´­Ìµ ¾ Note that ´ . A crucial property of type substitutions is that they preserve the validity of typing statements: if a term involving variables is well typed, then so are all of its

substitution instances.

` Ø : Ì 

17.1.2 Theorem [Preservation of typing under substitution]: If and is

` Ø : Ì ¾ any type substitution, then  .

Proof: Straightforward induction on typing derivations. ¾

17.2 Universal vs. Existential Type Variables

Suppose that Ø is a term containing type variables and is an associated envi- ronment (possibly also containing type variables). There are two quite different

questions that we can ask about Ø:

1. “Are all substitution instances of Ø well typed?” That is, is it the case that, for

 ` Ø : Ì Ì

every , we have for some ? 

2. “Is some substitution instance of Ø well typed?” That is, can we find a such

` Ø : Ì Ì that  for some ? According to the first view, type variables should be held abstract during typecheck- ing, thus ensuring that a well-typed term will behave properly no matter what concrete types are later substituted for its type variables. For example, the term

January 15, 2000 17. TYPE RECONSTRUCTION 120

f:X!Xº a:Xº f ´f aµ;

!Xµ!X!X X Ì

has type ´X , and, whenever we replace by , the instance

f:Ì!̺ a:̺ f ´f aµ; is well typed. Holding type variables abstract in this way leads to the idea of parametric polymorphism, in which type variables are used to encode the fact that a term can be used in many concrete contexts with different concrete types. We shall return to parametric polymorphism in more depth in Chapter 18.

In the second view, the original term Ø may not even be well typed; what we want to know is whether it can be instantiated to a well typed term by choosing

appropriate values for some of its type variables. For example, the term

f:Yº a:Xº f ´f aµ;

ÆaØ!ÆaØ X ÆaØ

is not typeable as it stands, but if we replace Y by and by , we obtain

f:ÆaØ! Æaغ a:Æaغ f ´f aµ;

!Æaص!ÆaØ!ÆaØ Y X!X of type ´ÆaØ . Or, if we simply replace by , we obtain the

term

f:X!Xº a:Xº f ´f aµ;

which is well typed even though it contains variables. Indeed, this term is a most

f:Yº a:Xº f ´f aµ general instance of  , in the sense that it makes the least com- mitment about the values of type variables that is required to obtain a well-typed term. We may even, in the limit, allow type annotations to be omitted completely, fill- ing in a fresh type variable during parsing whenever an annotation is discovered

to be missing. This allows the term above to be written

fº aº f ´f aµ; as in languages like ML. Looking for valid instantiations of type variables leads to the idea of type re- construction, in which the compiler is asked to help fill in type information that has been underspecified by the programmer. We develop this point of view in the

rest of the chapter.

Ø ´ ; ص ´; ̵

17.2.1 Definition: Let be a context and a term. A typing for is a pair

` Ø : Ì ¾

such that  .

= f:X; a:Y Ø = f a

17.2.2 Example: Let and . Then

´fX 7! Y!ÆaØg; Æaص

´fX 7! Y!Z; Z 7! ÆaØg; Zµ

´fX 7! Y!ÆaØ!ÆaØg; ÆaØ!Æaص

´fX 7! Y!Zg; Zµ

; ص ¾ are all typings for ´ . January 15, 2000 17. TYPE RECONSTRUCTION 121

17.2.3 Exercise [Quick check]: Find three different typings for

Ü:Xº Ý:Yº Þ:Zº ´Ü Þµ ´Ý Þµ:

with respect to the empty context. ¾

17.3 Constraint-Based Typing

We now give a different presentation of the typing relation in which, for example, instead of checking directly whether types of arguments match domains of func-

tions, we generate a set of constraints C recording the fact that this check should

be performed later.

i¾½::Ò

C fË = Ì g i

17.3.1 Definition: A constraint set is a set of equations i . A substi-

C i

tution  is said to satisfy the constraint set if, for each , the substitution instances

Ë Ì ¾ i

i and are equal.

` Ø : Ì j C

17.3.2 Definition: The constraint typing relation X is defined by the

` Ø : Ì j C Ø Ì

rules below. Informally, X can be read as “Term has type under as-

C X sumptions whenever constraints are satisfied.” The subscript , which tracks the type variables introduced in the process, is used for internal bookkeeping—to make sure that the fresh type variables used in different subderivations are actu-

ally distinct.

Ü:Ì ¾

(CT-VAR)

` Ü : Ì j fg

;

; Ü:Ë ` Ø : Ì j C Ü 6¾ ´ µ X ½ dom

(CT-ABS)

` Ü:輯 : Ë!Ì j C

½ X

` Ø : Ì j C ` Ø : Ì j C

½ ½ X ½ ¾ ¾ X ¾

½ ¾

X \X = ; X X X Ì Ì C C Ø Ø

¾ ½ ¾ ½ ¾ ½ ¾ ½ ¾ ½ not mentioned in , , , , , , , ,or

(CT-APP)

` Ø Ø : X j C [ C [ fÌ = Ì !Xg

½ ¾ ½ ¾ ½ ¾

X [X [fXg

½ ¾

` ¼ : ÆaØ j fg

; (CT-ZERO)

` Ø : Ì j C

½ X

(CT-SUCC)

` ×Ùcc Ø : ÆaØ j C [ fÌ = ÆaØg

½ X

` Ø : Ì j C ` Ø : Ì j C ` Ø : Ì j C

½ ½ X ½ ¾ ¾ X ¾ ¿ ¿ X ¿

½ ¾ ¿

X ; X ; X

¾ ¿

½ nonoverlapping

¼

C = C [ C [ C [ fÌ = ÆaØ; Ì = Ì !Ì g

½ ¾ ¿ ½ ¾ ¿ ¿

(CT-ITER)

¼

C ` iØeÖ Ì Ø Ø Ø : Ì j

½ ¾ ¿ ¿ X [X [X

½ ¾ ¿

As usual, these rules (when read from bottom to top) determine a straightforward

Ø Ì C X ` Ø : Ì j C procedure that, given and , calculates and (and ) such that X . January 15, 2000 17. TYPE RECONSTRUCTION 122

However, unlike the original typing algorithm, this one never fails, in the sense

Ø Ì C ` Ø : Ì j C

that for every and there are always some and such that ,

C Ø and moreover that Ì and are uniquely determined by and , up to the choice of

names of fresh type variables in X . (The nondeterminism arising from the freedom to choose different fresh type variable names will be addressed in Exercise 17.3.9.)

To lighten the notation in the following discussion, we usually elide the X and

` Ø : Ì j C ¾ write just . 17.3.3 Exercise [Quick check]: Construct a constraint typing derivation whose con-

clusion is

` Ü:Xº Ý:Yº Þ:Zº ´Ü Þµ ´Ý Þµ : Ë j C

C ¾

for some Ë and .

` Ø : Ë j C ´ ; Ø; Ë;Cµ

17.3.4 Definition: Suppose that .Atyping for is a pair

; ̵  C Ë = Ì ¾

´ such that satisfies and . Ø

Given a context and a term , we now have two different ways of calculating Ø sets of typings for and :

1. directly, via Definition 17.2.1; or

C ` Ø : Ë j C

2. via the constraint typing relation, by finding Ë and such that

; Ø; Ë;Cµ and then using Definition 17.3.4 to identify the set of typings for ´ .

Our next job is to show that these two methods yield essentially the same sets of

; Ø; Ë;Cµ

typings. We do this in two steps. First we show that every ´ -typing is a

; ص ´ ; ص

´ -typing [soundness]. Then we show that every -typing can be extended

; Ø; Ë;Cµ

to a ´ -typing [completeness].

` Ø : Ë j C

17.3.5 Theorem [Soundness of constraint typing]: Suppose that .If

; ̵ ´ ; Ø; Ë;Cµ ´ ; ص ¾

´ is a typing for , then it is also a typing for .

` Ø : Ë j C Proof: By induction on the given constraint typing derivation for ,

reasoning by cases on the last rule used.

= Ü

Case CT-VAR: Ø

Ü:Ë ¾

C = fg

` Ü : ´ µ´Üµ 

The result is immediate, since by T-VAR  for any .

Ø = Ü:Ì ºØ ½

Case CT-ABS: ½

Ë = Ì !Ë

½ ¾

; Ü:Ì ` Ø : Ë j C

½ ½ ¾

´; Ë µ ´´ ; Ü:Ì µ; Ø µ

½ ½

By the induction hypothesis, ¾ is a typing for , i.e.,

 ; Ü:Ì ` Ø : Ë :

½ ½ ¾

 ` Ü:Ì ºØ : Ì !Ë = ´Ì !Ë µ=Ì

½ ½ ¾ ½ ¾ By T-ABS, ½ , as required.

January 15, 2000 17. TYPE RECONSTRUCTION 123

Ø = Ø Ø ¾

Case CT-APP: ½

Ë = X

` Ø : Ë j C

½ ½ ½

` Ø : Ë j C

¾ ¾ ¾

C = C [ C [ fË = Ë !Xg

½ ¾ ½ ¾

 C C Ë = ´Ë !Xµ

¾ ½ ¾

By the definition of satisfaction, satisfies both ½ and and .

´; Ë µ ´; Ë µ ´ ; Ø ; Ë ;C µ

¾ ½ ½ ½

By Definition 17.3.4, we see that ½ and are typings for

´ ; Ø ; Ë ;C µ  ` Ø : Ë

¾ ¾ ½ ½

and ¾ , from which the induction hypothesis gives us

 ` Ø : Ë Ë = Ë !X  ` Ø : Ë !X

¾ ½ ¾ ½ ¾

and ¾ . But since , we then have ,

 ` ´Ø Ø µ : X = Ì ¾ and, by T-APP, ½ , as required. Other cases:

Left as an exercise. ¾

ÒX

17.3.6 Definition: Write  for the substitution that is undefined for all the vari-

 ¾

ables in X and otherwise behaves like .

` Ø : Ë j C

17.3.7 Theorem [Completeness of constraint typing]: Suppose X .If

¼

; ̵ ´ ; ص ´µ \X = ; ´ ; ̵

´ is a typing for and dom , then there is some typing for

¼

; Ø; Ë;Cµ  ÒX =  ¾ ´ such that .

Proof: By induction on the given constraint typing derivation.

= Ü

Case CT-VAR: Ø

Ü:Ë ¾

; ̵ ´ ; ܵ

From the assumption that ´ is a typing for , the inversion lemma for the

´ µ´Üµ ´; ̵ ´ ; Ü; Ë; fgµ typing relation (7.4.1) tells us that Ì is . But then is also a -

typing.

Ø = Ü:Ì ºØ ½

Case CT-ABS: ½

; Ü:Ì ` Ø : Ë j C

½ ½ ¾ X

Ë = Ì !Ë

½ ¾

´; ̵ ´ ;Ü:Ì ºØ µ ½

From the assumption that is a typing for ½ , the inversion lemma

 ; Ü:Ì ` Ø : Ì Ì = Ì ! Ì

½ ¾ ½ ¾

for the typing relation yields ½ and .

¼

´ ; Ì µ ´´ ;Ü:Ì µ; Ø ; Ë ;Cµ

½ ½ ¾

By the induction hypothesis, there is a typing ¾ for

¼ ¼ ¼ ¼

 ÒX   ´Ëµ =  ´Ì !Ë µ = Ì ! Ë =

¾ ½ ¾

such that agrees with . But then ½

¼

Ì !Ì = Ì ´ ; ̵ ´ ; ´Ü:Ì ºØ µ; Ì !Ë ;Cµ

¾ ½ ½ ½ ¾

½ ,so is a typing for .

Ø = Ø Ø ¾

Case CT-APP: ½

` Ø : Ë j C

½ ½ X ½

½

C ` Ø : Ë j

¾ ¾ ¾ X

¾

X X X Ë Ë C C X \X = ;

½ ¾ ½ ¾ ½ ¾ ¾

½ and not mentioned in , , , , ,

Ë = X

X = X [X [ fXg

½ ¾

C = C [ C [ fË = Ë !Xg

½ ¾ ½ ¾

January 15, 2000 17. TYPE RECONSTRUCTION 124

´; ̵ ´ ; Ø Ø µ ¾

From the assumption that is a typing for ½ , the inversion lemma for

 ` Ø : Ì !Ì  ` Ø : Ì

½ ¾ ½

the typing relation yields ½ and .

´ ; Ì !̵ ´ ; Ø ; Ë ;C µ

½ ½ ½ ½

By the induction hypothesis, there are typings ½ for and

´ ; Ì µ ´ ; Ø ; Ë ;C µ  ÒX  ÒX 

½ ¾ ¾ ¾ ½ ¾

¾ for , and and agree with . We must exhibit a

¼ ¼ ¼ ¼

 ÒX   X = Ì 

substitution  such that: (1) agrees with , (2) , and (3) satisfies

¼ ¼ ¼ ¼

fË = Ë !Xg  Ë =  Ë ! X 

¾ ½ ¾

½ , i.e., . Define as follows:

¼

Y = Y Y ¾X=

 if

¼

 Y =  Y Y ¾X ½

½ if

¼

 Y =  Y Y ¾X ¾

if ¾

¼

Y = Ì Y = X  if .

Conditions (1) and (2) are obviously satisfied. To check (3), calculate as follows:

¼ ¼ ¼ ¼

 Ë =  Ë = Ì !Ì =  Ë !Ì =  Ë ! X =  ´Ë !Xµ

½ ½ ½ ¾ ¾ ¾ ¾ ½ . Other cases:

Left as an exercise. ¾

` Ø : Ë j C ´ ; ص

17.3.8 Corollary: Suppose . There is some typing for iff there is

; Ø; Ë;Cµ ¾ some typing for ´ .

Proof: By Theorems 17.3.5 and 17.3.7. ¾ 17.3.9 Exercise [Recommended]: Because we have not described how the choice of fresh variable names actually occurs (beyond stipulating that they must be “fresh enough”), the constraint generation algorithm that we have been working with is actually nondeterministic. Fortunately, this nondeterminism is inessential and eas- ily eliminated. In a production compiler, the nondeterministic choice of a fresh type variable name in the rule CT-APP might be replaced by a call to a function that generates a new type variable—different from all others that it ever generates, and from all type variables mentioned explicitly in the context or term being checked—each

time it is called. Because this global “geÒ×ÝÑ” operation works by side effects on a hidden global variable, it is difficult to reason about it formally. However, we can easily simulate it by “threading” a sequence of unused variable names through the constraint generation rules.

Let F denote a sequence of fresh type variable names (with each element of the

sequence different from every other). Then, instead of writing

` Ø : Ì j C X

for the constraint generation judgement, we write

¼

` Ø : Ì j C;

F F

¼

F Ø Ì F C where , , and are inputs to the algorithm and , , and are outputs. When-

ever it needs a fresh type variable, the algorithm takes off the front element of F

¼ F and returns the rest of F as . January 15, 2000 17. TYPE RECONSTRUCTION 125

Write out the rules for this algorithm in detail. Prove that they are equivalent, in an appropriate sense, to the original constraint generation rules. (Solution on

page 256.) ¾

17.3.10 Exercise [Recommended]: Implement the algorithm discussed in Exercise 17.3.9

in ML. Use the datatype

ØÝÔe ØÝ =

ÌÝAÖÖ Óf ØÝ ¶ ØÝ

| ÌÝÁd Óf ×ØÖiÒg

| ÌÝBÓÓÐ

| ÌÝÆaØ

for types, and

ØÝÔe cÓÒ×ØÖ = ´ØÝ ¶ Øݵ Ði×Ø for constraint sets. You will also need a representation for infinite sequences of fresh variable names. There are lots of ways of doing this; here is a fairly direct one

using a recursive datatype:

ØÝÔe ÒeÜØÙÚaÖ = ÆeÜØÍÎaÖ Óf ×ØÖiÒg ¶ ÙÚaÖgeÒeÖaØÓÖ

aÒd ÙÚaÖgeÒeÖaØÓÖ = ÙÒiØ ! ÒeÜØÙÚaÖ

ÐeØ ÙÚaÖgeÒ =

ÐeØ Öec f Ò ´µ = ÆeÜØÍÎaÖ´"?X_" ^ ×ØÖiÒg_Óf_iÒØ Ò¸ f ´Ò·½µµ

iÒ f ¼ ´µ

That is, ÙÚaÖgeÒ is a function that, when called with argument , returns a value

Ü f of the form ÆeÜØÍÎaִܸfµ, where is a fresh type variable name and is another

function of the same form. (Solution on page 257.) ¾

17.4 Unification

We have given two different characterizations of the set of typings for a given term in a given context. But we have not addressed the algorithmic problem of deciding whether or not this set is empty—i.e., of deciding whether it is possible to replace type variables by types so as to make the term typeable in the ordinary sense. The key insight that we need, due to Hindley [?] and Milner [?], is that, if the set of typings of a term is nonempty, it always contains a “best” element, in the sense that the rest of the typings can be generated straightforwardly from this one. To show that such principal typings exist (and, in fact, to give an algorithm for generating them), we rely on the familiar operation of unification [?] on constraint sets.

January 15, 2000 17. TYPE RECONSTRUCTION 126

Ë Ì Ë = Ì

17.4.1 Definition: A substitution  is said to unify two types and if .

 C  Ë

So saying that “ satisfies the constraint set ” is the same as saying “ unifies i

Ì Ë = Ì C 

i i

and i for every equation in .” We sometimes speak of as a unifier for ¾ C.

17.4.2 Definition: We say that a substitution  is more general than a substitution

¼ ¼ ¼

 Ú   = ­ Æ  ­ ¾

 , written ,if for some substitution . 

17.4.3 Definition: A principal unifier for a constraint set C is a substitution that

¼ ¼

 Ú   C ¾ satisfies C and such that for every substitution that also satisfies .

17.4.4 Exercise [Quick check]: Write down principal unifiers (when they exist) for

the following sets of constraints:

fX = ÆaØ; Y = X!Xg

fÆaØ!ÆaØ = X!Yg

fX!Y = Y!Z; Z = Í!Ïg

fÆaØ = ÆaØ!Yg

fY = ÆaØ!Yg

fg (the empty set of constraints)

(Solution on page 258.) ¾

17.4.5 Definition: The unification algorithm is defined as follows:

Cµ C = ; fg

unify´ =if , then

¼

Ë = Ìg [ C = C

else let f in

= Ì

if Ë

¼

C µ

then unify´

= X X ¾= ´Ìµ

else if Ë and FV

¼

fX 7! ÌgC µ Æ fX 7! Ìg

then unify´

= X X ¾= ´Ëµ

else if Ì and FV

¼

fX 7! ËgC µ Æ fX 7! Ëg

then unify´

Ë = Ë !Ë Ì = Ì !Ì

¾ ½ ¾

else if ½ and

¼

´C [ fË = Ì ; Ë = Ì gµ

½ ¾ ¾ then unify ½ else

fail 

where C is the constraint set formed by applying to both sides of all the con- ¾ straints in C.

17.4.6 Theorem: The algorithm unify always terminates, fails only when given a non-unifiable constraint set as input, and otherwise returns a principal unifier.

More formally:

Cµ C 1. unify´ halts, either by failing or by returning a substitution, for all ;

January 15, 2000 17. TYPE RECONSTRUCTION 127

Cµ=  C

2. if unify´ , then is a unifier for ;

C ´Cµ=  Ú Æ ¾

3. if Æ is a unifier for , then unify with .

´Ñ; Òµ

Proof: For part (1), define the degree of a constraint set C to be the pair ,

C Ò where Ñ is the number of distinct type variables in and is the total size of

the types in C. It is easy to check that each clause of the unify algorithm either terminates immediately (with success in the first case or failure in the last) or else makes a recursive call to unify with a constraint set of smaller degree.

Part (2) is a straightforward induction on the number of recursive calls in the

computation of unify´ . All the cases are trivial except for the two involving vari-

¼

fX 7! ÌgC  Æ fX 7! Ìg

ables, which depend on the observation that, if  unifies , then

¼

X = Ìg [ C unifies f .

Part (3) again proceeds by induction on the number of recursive calls in the

Cµ C ´Cµ fg

computation of unify´ .If is empty, then unify immediately returns ; since

= Æ Æ fg fg Ú Æ C ´Cµ

Æ , we have as required. If is non-empty, then unify chooses

Ë; ̵ C Ë Ì

some pair ´ from and continues by cases on the shapes of and .

= Ì

Case: Ë

¼

C C ´Cµ=

Since Æ is a unifier for , it also unifies . By the induction hypothesis, unify

 Ú Æ

 with , as required.

= X X ¾= Ì

Case: Ë and

Ë Ì Æ´Xµ=ƴ̵ Í Æ´Íµ=

Since Æ unifies and , we have . So, for any type , we have

¼ ¼

´fX 7! Ìg͵ Æ C fX 7! ÌgC

Æ ; in particular, since satisfies it must also satisfy . The

¼ ¼ ¼

fX 7! ÌgC µ =  Æ = ­ Æ 

induction hypothesis then tells us that unify´ , with

¼ ¼

´Cµ =  Æ fX 7! Ìg Æ = ­ Æ ´ Æ fX 7! Ìgµ

for some ­. Since unify , showing that

Y 6= X

will complete the argument. Choose any type variable Y.If , then clearly

¼ ¼ ¼

­ Æ ´ Æ fX 7! ÌgµµY =´­ Æ  µY = ÆY ´­ Æ ´ Æ fX 7! ÌgµµX =

´ . On the other hand,

¼

­ Æ  µÌ = ÆX ÆY =

´ , as we saw above. Combining these observations, we see that

¼ ¼

­ Æ ´ Æ fX 7! ÌgµµY Y Æ =´­ Æ ´ Æ fX 7! Ìgµµ

´ for all variables , i.e. .

= X X ¾= Ë Case: Ì and

Similar.

Ë = Ë !Ë Ì = Ì !Ì

¾ ½ ¾

Case: ½ and

¼

Æ fË !Ë = Ì !Ì g [ C

¾ ½ ¾

Straightforward. Just note that is a unifier of ½ iff it is a

¼

C [ fË = Ì ; Ë = Ì g

½ ¾ ¾

unifier of ½ .

Ì ´Cµ

If none of the above cases apply to Ë and , then unify fails. But this can

ÆaØ Ì

only happen in two ways: either Ë is and is an arrow type (or vice versa),

= X X ¾ Ì or else Ë and (or vice versa). The first case obviously contradicts the

assumption that C is unifiable. To see that the second does too, recall that, by

Ë = ÆÌ X Ì ÆÌ

assumption, Æ ;if occurred in , then would always be strictly larger

Ë ´Cµ C ¾ than Æ . Thus, unify never fails when is satisfiable.

17.4.7 Exercise [Recommended]: Implement the unification algorithm in ML. January 15, 2000 17. TYPE RECONSTRUCTION 128

The main data structure needed for this exercise is a representation of substitu-

tions. There are many alternatives; one simple one is to reuse the cÓÒ×ØÖ datatype from Exercise 17.3.10: a substitution is just a constraint set, all of whose left-hand

sides are unification variables. If ×Ùb×ØiÒØÝ is a function that performs substitu-

tion of a type for a single type variable

ÐeØ ×Ùb×ØiÒØÝ ØÝX ØÝÌ ØÝË =

ÐeØ Öec Ó = fÙÒcØiÓÒ

ÌÝAÖÖ´ØÝ̽¸ØÝ̾µ ! ÌÝAÖÖ´Ó ØÝ̽¸ Ó ØÝ̾µ

| ÌÝÆaØ ! ÌÝÆaØ

| ÌÝBÓÓÐ ! ÌÝBÓÓÐ

| ÌÝÁd´×µ ! if ×=ØÝX ØheÒ ØÝÌ eÐ×e ÌÝÁd´×µ

iÒ Ó ØÝË

then application of a whole substitution to a type can be defined as follows:

ÐeØ aÔÔÐÝ×Ùb×Ø cÓÒ×ØÖ ØÝÌ =

Äi×غfÓÐd_ÐefØ

´fÙÒ ØÝË ´ÌÝÁd´ØÝXµ¸ØÝC¾µ ! ×Ùb×ØiÒØÝ ØÝX ØÝC¾ ØÝ˵

ØÝÌ cÓÒ×ØÖ

(Solution on page 258.) ¾

17.5 Principal Typings

; Ø; Ë;Cµ ´; ̵

17.5.1 Definition: A principal typing for ´ is a typing such that,

¼ ¼ ¼

 ; Ì µ ´ ; Ø; Ë;Cµ  Ú  ¾ whenever ´ is also a typing for , we have .

17.5.2 Exercise [Quick check]: Find a principal typing for

Ü:Xº Ý:Yº Þ:Zº ´Ü Þµ ´Ý Þµ: ¾

; Ø; Ë;Cµ 17.5.3 Theorem [Principal typing]: If ´ has any typing, then it has a prin-

cipal one. Moreover, the unification algorithm can be used to determine whether

; Ø; Ë;Cµ ¾ ´ has a typing and, if so, to return a principal one.

Proof: Immediate from the definition of typing and the properties of unification. ¾

; ص ¾ 17.5.4 Corollary: It is decidable whether ´ has a typing.

Proof: By Corollary 17.3.8 and Theorem 17.5.3. ¾

17.5.5 Exercise [Recommended]: Use the implementations of constraint genera- tion (Exercise 17.3.10) and unification (Exercise 17.4.7) to construct a running type-

checker that calculates principal typings, using the ×iÑÔÐe checker provided in the

course directory as a starting point. ¾ January 15, 2000 17. TYPE RECONSTRUCTION 129

17.5.6 Exercise: What difficulties arise in extending the basic definitions (17.3.2,

etc.) to deal with records? How might they be addressed? (Solution on page 259.) ¾

Principal typings can be used to build a type reconstruction algorithm that works more incrementally than the one we have developed here. Instead of gen- erating all the constraints first and then trying to solve them, we can interleave generation and solving, so that the type reconstruction algorithm actually returns a principal typing at each step. The fact that the typings are always principal is what ensures that the algorithm never needs to go back and re-analyze a subterm that it has already processed, since it makes only the minimum commitments needed to achieve typeability at each step. One major advantage of such an algorithm is that it can pinpoint errors in the user’s program much more precisely.

17.5.7 Exercise: Modify your solution to Exercise 17.5.5 to perform unification in-

crementally during typechecking and return principal typings. ¾

17.6 Further Reading Chapter 18

Universal Types

Type structure is a syntactic discipline for enforcing levels of abstraction. — John Reynolds [Rey83]

Some writing needed.

18.1 Motivation

As we observed at the beginning of Chapter 13, the pure simply typed lambda- calculus is a rather restrictive system in some respects, if we consider it as the basis

for a programming language. Although we can enrich it with numerous additional

BÓÓÐ ÍÒiØ

type constructors (references, lists, etc.), primitive types (ÆaØ, , , etc.), and fiÜ convenient control constructs (ÐeØ, , etc.), the rigidity of the “core” typing rules can make it difficult to exploit these features to full advantage. In Chapter 13, we explored one way of refining the typing relation to make it much more flexible: adding a subtyping relation and allowing types of terms to be “promoted” when matching the types of functions and their arguments.

In this chapter, we introduce another, rather different, way of adding flexibility ! to the core type system. To motivate this extension, note that in  there are an

infinite number of “doubling” functions

dÓÙbÐeÆaØ = f:ÆaØ!Æaغ Ü:Æaغ f ´f ܵ;

dÓÙbÐeÊcd = f:ßÐ:ÆaØ}! ßÐ:ÆaØ}º Ü:ßÐ:ÆaØ}º f ´f ܵ;

dÓÙbÐeÊcd = f:´ÆaØ! Æaص!´ÆaØ! Æaصº Ü:ÆaØ! Æaغ f ´f ܵ;

´eØcºµ

Á

dÓÙbÐeÆaØ : ´ÆaØ!Æaص ! ÆaØ ! ÆaØ

dÓÙbÐeÊcd : ´ßÐ:ÆaØ}! ßÐ:ÆaØ}µ ! ßÐ:ÆaØ} ! ßÐ:ÆaØ}

dÓÙbÐeÊcd : ´´ÆaØ! Æaص!ÆaØ! Æaص ! ´ÆaØ! Æaص ! ÆaØ ! ÆaØ

130 January 15, 2000 18. UNIVERSAL TYPES 131 each applicable to a different type of argument, but all sharing precisely the same behavior (even the same program text, modulo typing annotations). This kind of “cut and paste” programming violates a basic principle of software engineering: Write each piece of functionality in one place. If something has to be used many times in slightly different ways, abstract out the varying parts. Here, the varying parts are the types! What we want, it seems, are facilities for “abstracting out” a type from a term and later instantiating this abstract (or “poly- morphic”) term by applying it to a concrete type. The system we’ll be studying in this chapter was developed (one is tempted to say “discovered”) independently, in the early 1970s by a computer scientist, John Reynolds, who called it the polymorphic lambda-calculus [Rey74], and by a logician, Jean-Yves Girard, who called it System F [Gir72]. It has been used extensively as a research vehicle for foundational work on polymorphism and as the basis for numerous programming language designs. For reasons that we shall see later (in Chapter 25), it is sometimes called the second-order lambda-calculus.

18.2 Varieties of Polymorphism

Type systems that allow a single piece of code to be used with multiple types are collectively known as polymorphic systems. Several types of polymorphism have been proposed (this way of classifying them is due to Strachey [?]): Parametric polymorphism, the subject of this chapter, allows a piece of code to be typechecked “generically,” using type variables in place of actual types, and then instantiated with particular types as needed. We have seen this phenomenon already in Chapter ??, and it will be the main focus of the present chapter. Ad-hoc polymorphism allows different behaviors at run-time when a single piece of code is used with multiple types. The most powerful

form of ad-hoc polymorphism is a general ØÝÔeca×e construct that al- lows arbitrary computation based on type information, but this is sel- dom seen in real languages. More common are constructs such as Java’s

ha×ÌÝÔe , which allow simple branching on run-time type tags. Overloading is a very simple form of ad-hoc polymorphism where only a limited collection of (usually built-in) operations are given multi-

ple types. For example, many languages overload arithmetic operators

ÁÒØ!ÁÒØ!ÁÒØ ÊeaÐ!ÊeaÐ!ÊeaÐ like · with multiple types such as and . The subtype polymorphism that we saw in Chapter 13 gives a single term many types using the rule of subsumption, allowing us to selec- tively “forget” information about the term’s behavior. January 15, 2000 18. UNIVERSAL TYPES 132

These categories are not exclusive: different forms of polymorphism can be mixed in the same language. For example, Standard ML offers a restricted form of para- metric polymorphism and simple arithmetic overloading, but not subtyping, while Java includes subtyping, overloading, and simple ad-hoc polymorphism, but not parametric polymorphism. (There are numerous proposals for adding parametric polymorphism to Java. At the time of this writing, the front-runner is probably GJ [BOSW98].) The bare term “polymorphism” is the source of a certain amount of confusion in the programming languages literature. In the functional programming commu- nity (i.e., those who use or design languages like ML, Haskell, etc.), it always refers to parametric polymorphism. In the object-oriented programming community, it almost always refers to subtype polymorphism.

18.3 Definitions

The definition of the polymorphic lambda-calculus (System F for short) is actu- ! ally a very straightforward extension of the simply typed lambda-calculus. In  , lambda-abstraction is used to abstract terms out of terms, and application is used to supply values for the abstracted parts. Similarly, we want a mechanism for ab- stracting types out of terms and filling them in later—we might as well use lambda- abstraction and application as a model. To this end, we introduce a new form of

lambda-abstraction

Xº Ø

whose parameter is a type—a kind of function that takes a type X as argument.

Similarly, we introduce a new form of application

Ø [Ì] in which the argument is a type expression. We call our new functions with type parameters polymorphic functions or type abstractions; the new application con- struct is called type application.

When, during evaluation, a type abstraction meets a type application, the pair ! forms a redex, just as in  . We add a reduction rule analogous to the ordinary reduction rule for abstractions and applications. For

example, when the polymorphic identity function

id = Xº Ü:Xº Ü;

fX 7! ÆaØg´Ü:XºÜµ Ü:ÆaØºÜ is applied to the argument ÆaØ, the result is , i.e., , which is the identity function on natural numbers.

Finally, we need to define the type of a polymorphic function. Just as we had

!ÆaØ Ü:ÆaØºÜ types like ÆaØ for classifying ordinary functions like , we now need January 15, 2000 18. UNIVERSAL TYPES 133

a different form of “arrow type” whose domain is a type, for classifying polymor-

Ì id

phic functions like id. Notice that, for each argument to which it is applied,

!Ì id yields a function of type Ì ; that is, the type of the result of depends on the actual type that we pass it as argument. To capture this dependency, we write the

type of id like this:

id : 8XºX!X

The typing rules for polymorphic abstraction and application are analogous to

the corresponding rules for ordinary abstraction and application.

; X ` Ø : Ì

¾ ¾

(T-TABS)

` XºØ : 8XºÌ

¾ ¾

` Ø : 8XºÌ

½ ½¾

(T-TAPP)

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾

Note that we include the “binding” X in the typing context used in the subderiva-

tion for Ø. For the moment, this binding plays no role except to keep track of the scopes of type variables and make sure that the same type variable is not added twice to the context. In later chapters, we will annotate type variable bindings in the context with information of various kinds.

In summary, here is the complete polymorphic lambda-calculus, with differ- !

ences from  highlighted. 8 System F : Polymorphic lambda-calculus !

Syntax

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø

Ø application XºØ

 type abstraction [Ì] Ø type application

Ú ::= (values...)

Ü:̺Ø

 abstraction value XºØ  type abstraction value

Ì ::= (types...)

X type variable

Ì type of functions

XºÌ 8 universal type

::= (contexts...) January 15, 2000 18. UNIVERSAL TYPES 134

; empty context Ü:Ì

; term variable binding X

; type variable binding

¼

! Ø

Evaluation (Ø )

´Ü:Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

´XºØ µ [Ì ] ! fX 7! Ì gØ

¾ ¾ ½¾

½¾ (E-BETA2)

¼

Ø ! Ø ½

½ (E-TAPP)

¼

Ø [Ì ] ! Ø [Ì ]

½ ¾ ¾

½

` Ø : Ì

Typing ( )

Ü:Ì ¾

(T-VAR)

` Ü : Ì

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

; X ` Ø : Ì ¾

¾ (T-TABS)

` XºØ : 8XºÌ

¾ ¾

` Ø : 8XºÌ ½¾

½ (T-TAPP)

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾

As usual, this summary defines just the “pure” polymorphic lambda-calculus, BÓÓÐ

omitting other type constructors such as records, base types such as ÆaØ and , fiÜ and term-language extensions such as ÐeØ and . These extra constructs can be added straightforwardly to the pure system, and we will use them freely in the examples that follow.

18.3.1 Exercise [Quick check]: In Exercise 7.3.1, we saw that the pure simply typed lambda calculus (with no base types or type variables) is actually a trivial system

containing no typeable terms. What about pure System F? ¾ January 15, 2000 18. UNIVERSAL TYPES 135

18.4 Examples

We now turn to developing some more interesting examples of “programming with polymorphism,” of several different sorts:

¯ To warm up, we’ll start with a few small but increasingly tricky examples, showing some of the expressive power of System F.

¯ We’ll then review the basic ideas of “ordinary” polymorphic programming with lists, trees, etc. This is the kind of programming that usually comes to mind when polymorphism is mentioned.

¯ The final subsection will introduce typed versions of the Church Encodings of simple algebraic datatypes like booleans, numbers, and lists that we saw in Chapter 4 for the untyped lambda-calculus. Although these encodings are of little practical importance, they make excellent exercises for understanding the intricacies of System F.

Warm-ups We have seen already how type abstraction and application can be used to define

a single polymorphic identity function

id = Xº Ü:Xº Ü; and instantiate it to yield any particular concrete identity function that may be

required:

id [ÆaØ];

Á

id : 8Xº X ! X

´Ü:Æaغ ܵ : ÆaØ ! ÆaØ

id [ÆaØ] ¼;

Á

¼ : ÆaØ

A more useful example is the polymorphic “double” function, which takes a

a f a

function f and an argument and applies twice in succession to :

dÓÙbÐe = Xº f:X! Xº a:Xº f ´f aµ;

Á

dÓÙbÐe : 8Xº ´X! Xµ ! X ! X

The abstraction on the type X allows us to obtain doubling functions for specific

types by instantiating dÓÙbÐe with different type arguments:

dÓÙbÐeÆaØ = dÓÙbÐe [ÆaØ];

dÓÙbÐeÆaØAÖÖÓÛÆaØ = dÓÙbÐe [ÆaØ! ÆaØ];

January 15, 2000 18. UNIVERSAL TYPES 136

Á

dÓÙbÐeÆaØ : ´ÆaØ!Æaص ! ÆaØ ! ÆaØ

dÓÙbÐeÆaØAÖÖÓÛÆaØ : ´´ÆaØ! Æaص!ÆaØ! Æaص ! ´ÆaØ! Æaص ! ÆaØ ! ÆaØ

Once instantiated with a type argument, dÓÙbÐe can be further applied to an actual

function and an argument of appropriate types:

dÓÙbÐe [ÆaØ] ´Ü:Æaغ ×Ùcc´×Ùcc´Üµµµ ¿;

Á

7 : ÆaØ

Here is a slightly trickier example: polymorphic self-application. Recall that, in

the simply typed lambda-calculus, there is no way to give a typing to an untyped Ü term of the form Ü (cf. Exercise 7.4.5). In System F, on the other hand, this term

becomes typeable if we make Ü a polymorphic function and add a type application:

×eÐfAÔÔ = Ü:8XºX! Xº Ü [8XºX!X] Ü;

Á

×eÐfAÔÔ : ´8Xº X!Xµ ! ´8Xº X ! Xµ

Here is a more useful example of self application. We can apply the polymor-

phic dÓÙbÐe function to itself, yielding a polymorphic quadrupling function:

ÕÙadÖÙÔÐe = Xº dÓÙbÐe [X!X] ´dÓÙbÐe [X]µ;

Á

ÕÙadÖÙÔÐe : 8Xº ´X!Xµ ! X ! X

18.4.1 Exercise [Quick check]: Using the typing rules above, convince yourself that

these terms have the types given. ¾

Polymorphic Lists Impredicative Encodings

Here are the “Church booleans”:

CBÓÓÐ = 8XºX!X!X;

ØØ = Xº Ø:Xº f:Xº Ø;

ff = Xº Ø:Xº f:Xº f;

cif = b:CBÓÓк Xº Øh:Xº eÐ:Xº b [X] Øh eÐ;

Á

ØØ : 8Xº X ! X ! X

ff : 8Xº X ! X ! X

cif : CBÓÓÐ ! ´8Xº X ! X ! Xµ CBÓÓÐ In fact, cif is the identity function! In other words, an element of type is

itself a “conditional,” in the sense that it takes two alternatives and chooses either faÐ×e

the first or the second depending on whether it represents ØÖÙe or . cif We can write common boolean operations like ÒÓØ either in terms of

January 15, 2000 18. UNIVERSAL TYPES 137

ÒÓØ = b:CBÓÓк cif b [CBÓÓÐ] ff ØØ;

Á

ÒÓØ : CBÓÓÐ ! CBÓÓÐ

or, more interestingly, by directly constructing a new boolean from the given one:

ÒÓØ = b:CBÓÓк

Xº Ø:Xº f:Xº

b [X] f Ø;

Á

ÒÓØ : CBÓÓÐ ! ´8Xº X ! X ! Xµ

18.4.2 Exercise [Recommended]: Write a term

aÒd : CBÓÓÐ!CBÓÓÐ!CBÓÓÐ ¾ without using cif.

We can play a similar game with numbers. The elements of the type

CÆaØ = 8Xº ´X!Xµ ! X ! X;

of “Church numerals” can be used to represent natural numbers as follows:

cÞeÖÓ = Xº ×:X!Xº Þ:Xº Þ;

cÓÒe = Xº ×:X!Xº Þ:Xº × Þ;

cØÛÓ = Xº ×:X!Xº Þ:Xº × ´× Þµ;

cØhÖee = Xº ×:X!Xº Þ:Xº × ´× ´× Þµµ;

Á

cÞeÖÓ : 8Xº ´X!Xµ ! X ! X

cÓÒe : 8Xº ´X!Xµ ! X ! X

cØÛÓ : 8Xº ´X!Xµ ! X ! X

cØhÖee : 8Xº ´X! Xµ ! X ! X

× Þ

and so on. That is, a church numeral Ò is a function that, given arguments and ,

Þ Ò applies × to , times.

The successor function can be defined as follows:

c×Ùcc = Ò:CÆaغ

Xº ×:X!Xº Þ:Xº

× ´Ò [X] × Þµ;

Á

c×Ùcc : CÆaØ ! ´8Xº ´X!Xµ ! X ! Xµ

Ò CÆaØ × Þ × Þ Ò That is, c×Ùcc returns an element of that, given and , applies to ,

times (by applying Ò), and then once more.

Other arithmetic operations can be defined similarly:

cÔÐÙ× = Ñ:CÆaغ Ò:CÆaغ

Ñ [CÆaØ] c×Ùcc Ò;

Á

cÔÐÙ× : CÆaØ ! CÆaØ ! CÆaØ January 15, 2000 18. UNIVERSAL TYPES 138

Or, more directly:

cÔÐÙ× = Ñ:CÆaغ Ò:CÆaغ

Xº ×:X!Xº Þ:Xº

Ñ [X] × ´Ò [X] × Þµ;

Á

cÔÐÙ× : CÆaØ ! CÆaØ ! ´8Xº ´X!Xµ ! X ! Xµ

We can convert from church numerals to ordinary numbers like this:

cÒaؾÒaØ = Ñ:CÆaغ Ñ [ÆaØ] ´Ü:Æaغ ×Ùcc´Üµµ ¼;

Á

cÒaؾÒaØ : CÆaØ ! ÆaØ

This allows us to verify that the terms we have defined actually compute the de-

sired arithmetic functions:

cÒaؾÒaØ ´cÔÐÙ× ´c×Ùcc cÞeÖÓµ ´c×Ùcc ´c×Ùcc cÞeÖÓµµµ;

Á

¿ : ÆaØ ØÖÙe

18.4.3 Exercise [Recommended]: Write a function i×ÞeÖÓ that returns when

faÐ×e ¾ applied to the church numeral cÞeÖÓ and otherwise.

18.4.4 Exercise: Show that the terms

cØiÑe× = Ñ:CÆaغ Ò:CÆaغ

Xº ×:X!Xº

Ò [X] ´Ñ [X] ×µ;

ceÜÔ = Ñ:CÆaغ Ò:CÆaغ

Xº

Ò [X!X] ´Ñ [X]µ;

Á

cØiÑe× : CÆaØ ! CÆaØ ! ´8Xº ´X!Xµ ! X ! Xµ

ceÜÔ : CÆaØ ! CÆaØ ! ´8Xº ´X!Xµ ! X ! Xµ have the indicated types. Sketch an informal argument that they implement the

arithmetic multiplication and exponentiation operators. ¾

So, if we wanted to, we could actually drop ÆaØ and iteration from the lan- guage. This doesn’t affect real programming languages based on System F, since we want to build in booleans for efficiency and syntactic convenience, but it helps when we’re doing theoretical work because it keeps the system small.

18.4.5 Exercise [Recommended]: In what sense does the type

ÈaiÖÆaØ = 8Xº ´CÆaØ! CÆaØ!Xµ ! X; represent pairs of numbers? Write functions

January 15, 2000 18. UNIVERSAL TYPES 139

ÔaiÖÆaØ : CÆaØ! CÆaØ! ÈaiÖÆaØ;

f×ØÆaØ : ÈaiÖÆaØ! CÆaØ;

×ÒdÆaØ : ÈaiÖÆaØ! CÆaØ; for constructing elements of this type from pairs of numbers and for accessing their

first and second components. ¾

18.4.6 Exercise [Moderately difficult, recommended]: Use the functions defined

in Exercise 18.4.5 to write a function ÔÖed that computes the predecessor of a ¼

church numeral (returning ¼ if its input is ). (Hint: the key idea is developed

: ÈaiÖÆaØ!ÈaiÖÆaØ

in the example in Section ??. Define a function f that maps

i; jµ ´i · ½; iµ the pair ´ into —that is, it throws away the second component of its

argument, copies the first component to the second, and increments the first. Then

f ´¼; ¼µ ´Ò; Ò ¹ ½µ ¾ Ò applications of to the starting pair yields the pair ...)

18.4.7 Exercise [Optional]: There is another way of computing the predecessor

ܺ ݺ Ü

function on church numerals. Let à stand for the untyped lambda-term

ܺ Ü

and Á for . The untyped lambda-term

ÚÔÖed = [Ò] ׺ Þº Ò ´Ôº Õº Õ ´Ô ×µµ ´Ã Þµ Á

(due to J. Velmans) computes the predecessor of an untyped Church numeral. Show that this term can be typed in System F by adding type abstractions and ap- plications as necessary and annotating the bound variables in the untyped term with appropriate types. For extra credit, explain why it works! (Solution on

page ??.) [Thanks to Michael Levin for making me aware of this example.] ¾

18.5 Metatheory

Soundness The preservation and progress properties from the simply typed lambda-calculus holds ex- actly the same here. To prove it, we need one additional substitution lemma, for types.

Strong Normalization The strong normalization property for System F, proved using an extension of the method presented in Chapter ??, was one of the major achievements of Girard’s Ph.D. thesis. Since then, this proof technique has been studied and reworked by many authors, including [?].

18.5.1 Theorem [Strong normalization]: All well-typed System F terms are strongly

normalizing. ¾ January 15, 2000 18. UNIVERSAL TYPES 140

Erasure and Typeability There are two reasonable definitions of erasure for System F: the “type-passing” and “type- forgetting” interpretations...

18.5.2 Exercise: The strong normalization property of System System F implies

that the term

ª = ´ܺ Ü Üµ ´ݺ Ý Ýµ in the untyped lambda-calculus cannot be typed in System F, since reduction of

ª never reaches a normal form. However, it is possible to give a more direct,

“combinatorial” proof of this fact, using just the rules defining the typing relation. Ü:̺Ø

1. Let us call a System F term exposed if it is a variable, an abstraction  ,

× XºØ

or an application Ø (i.e., if it is not a type abstraction or type applica- Ë

tion Ø ).

´Øµ=Å

Show that if Ø is well typed (in some context) and erase , then there is

´×µ=Å × some exposed term × such that erase and is well typed (possibly in a

different context). XºØ

2. Write  as shorthand for a nested sequence of type abstractions of the

X º X ºØ Ø [A] Ò

form ½ ... . Similarly, write for a nested sequence of type

´´Ø [A ]µ :::[A ]µ [A ] 8XºÌ

Ò¹½ Ò

applications ½ and for a nested sequence of

8X º 8X ºÌ Ò polymorphic types ½ ... . Note that these sequences are allowed to

be empty. For example, if X is the empty sequence of type variables, then

XºÌ Ì

8 is just .

ص=Å ` Ø : Ì ×

Show that if erase ´ and , then there exists some of the form

Xº ´Ù [A]µ X

 , for some sequence of type variables , some sequence of types

Ù ´×µ=Å ` × : Ì

A, and some exposed term , with erase and .

Ì ´Øµ = Å Æ

3. Show that if Ø is an exposed term of type (under ) and erase ,

× Ù × Ù ´×µ = Å

then Ø has the form for some terms and such that erase and

Ùµ=Æ ` × : Í!Ì ` Ù : Í

erase ´ , with and .

¾ ` Ù : Í ´Ùµ=Ü Ü

4. Suppose that Ü:Ì . Show that if and erase , then either

Ì = 8XºX X ¾ X i

(a) i , where , or else

Ì = 8X X ºÌ !Ì fX X 7! AgÌ = fX 7! Bg´8ZºÌ !Ì µ

¾ ½ ¾ ½ ¾ ½ ½ ½ ¾

(b) ½ , where for

A B jAj = jX X j jBj = jX j

¾ ½

some sequences of types and with ½ and .

´×µ=ܺŠ` × : Ë Ë 8XºË !Ë ¾

5. Show that if erase and , then has the form ½ ,

X Ë Ë ¾ for some , ½ , and . January 15, 2000 18. UNIVERSAL TYPES 141

6. Define the leftmost leaf of a type Ì as follows:

Xµ = X

leftmost-leaf´

Ë!̵ = ´Ëµ

leftmost-leaf´ leftmost-leaf

8XºËµ = ´Ëµ:

leftmost-leaf´ leftmost-leaf

fX X 7! Ag´8YºÌ µ=fX 7! Bg´8Zº´8YºÌ µ!Ì µ ´Ì µ=

¾ ½ ½ ½ ¾ ½

Show that if ½ , then leftmost-leaf

X X ¾ X X

i ½ ¾ i for some .

7. Show that ª is not typeable in System F.

(Solution on page ??.) ¾

The type erasure function for System F is the following mapping from System

F to terms in the untyped lambda-calculus:

ܵ = Ü

erase ´

Ü:̺ ص = ܺ ´Øµ

erase ´ erase

Ø ×µ = ´Øµ ´×µ

erase ´ erase erase

Xº ص = ´Øµ

erase ´ erase

Ø [Ë]µ = ´Øµ erase ´ erase

A term Å in the untyped lambda-calculus is said to be typeable in System F if there

´Øµ=Å is some well-typed term Ø such that erase .

Type Reconstruction 18.6 Implementation

Nameless Representation of Types

ML Code

ØÝÔe ØÝ =

ººº

| ÌÝÎaÖ Óf iÒØ ¶ iÒØ

| ÌÝAÐÐ Óf ×ØÖiÒg ¶ ØÝ

ØÝÔe ØeÖÑ =

ººº

| ÌÑÌAb× Óf iÒfÓ ¶ ×ØÖiÒg ¶ ØeÖÑ

| ÌÑÌAÔÔ Óf iÒfÓ ¶ ØeÖÑ ¶ ØÝ

ÐeØ ØÝ×hifØi d c ØÝÌ =

ØÝÑaÔ

´fÙÒ c Ü Ò ! if Ü>=c ØheÒ

January 15, 2000 18. UNIVERSAL TYPES 142

if Ü·d<¼ ØheÒ eÖÖ "ËcÓÔiÒg eÖÖÓÖ!"

eÐ×e ÌÝÎaÖ´Ü·d¸Ò·dµ

eÐ×e ÌÝÎaִܸҷdµµ

c

ØÝÌ

ÐeØ ØÑ×hifØi d c Ø =

ØÑÑaÔ

´fÙÒ fi c Ü Ò ! if Ü>=c ØheÒ ÌÑÎaÖ´fi¸Ü·d¸Ò·dµ eÐ×e ÌÑÎaÖ´fi¸Ü¸Ò·dµµ

´ØÝ×hifØi dµ

c

Ø

ÐeØ ØÑ×hifØ Ø d = ØÑ×hifØi d ¼ Ø

ÐeØ ØÝ×hifØ ØÝÌ d = ØÝ×hifØi d ¼ ØÝÌ

(Note that we also need to shift the type annotation in the ÌÑAb× case.)

ÐeØ ØÑ×Ùb×Øi × j Ø =

ØÑÑaÔ

´fÙÒ fi j Ü Ò ! if Ü=j ØheÒ ´ØÑ×hifØ × jµ eÐ×e ÌÑÎaÖ´fi¸Ü¸Òµµ

´fÙÒ j ØÝÌ ! ØÝ̵

j

Ø

ÐeØ ØÑ×Ùb×Ø × Ø = ØÑ×Ùb×Øi × ¼ Ø

ÐeØ ØÑ×Ùb×Ø×ÒiÔ × Ø = ØÑ×hifØ ´ØÑ×Ùb×Ø ´ØÑ×hifØ × ½µ ص ´¹½µ

ÐeØ ØÝ×Ùb×Øi ØÝË j ØÝÌ =

ØÝÑaÔ

´fÙÒ j Ü Ò ! if Ü=j ØheÒ ´ØÝ×hifØ ØÝË jµ eÐ×e ´ÌÝÎaִܸҵµµ

j

ØÝÌ

ÐeØ ØÝ×Ùb×Ø ØÝË ØÝÌ = ØÝ×Ùb×Øi ØÝË ¼ ØÝÌ

ÐeØ ØÝ×Ùb×Ø×ÒiÔ ØÝË ØÝÌ = ØÝ×hifØ ´ØÝ×Ùb×Ø ´ØÝ×hifØ ØÝË ½µ ØÝ̵ ´¹½µ

ÐeØ Öec ØÝØÑ×Ùb×Øi ØÝË j Ø =

ØÑÑaÔ

´fÙÒ fi c Ü Ò ! ÌÑÎaÖ´fi¸Ü¸Òµµ

´fÙÒ j ØÝÌ ! ØÝ×Ùb×Øi ØÝË j ØÝ̵

j

Ø

ÐeØ ØÝØÑ×Ùb×Ø ØÝË Ø = ØÝØÑ×Ùb×Øi ØÝË ¼ Ø

January 15, 2000 18. UNIVERSAL TYPES 143

ÐeØ ØÝØÑ×Ùb×Ø×ÒiÔ ØÝË Ø = ØÑ×hifØ ´ØÝØÑ×Ùb×Ø ´ØÝ×hifØ ØÝË ½µ ص ´¹½µ

18.7 Further Reading Chapter 19

Existential Types

Some writing needed. Having seen the role of universal quantifiers in a type system, one might won- der whether existential quantifiers would also be useful in programming. In fact, they provide an elegant foundation for data abstraction and “information hiding,” as we shall see in this chapter.

19.1 Motivation

The polymorphic types in Chapter 18 can be viewed in two different ways: XºÌ

1. A logical intuition is that an element of the type 8 is a value that has type

X 7! ËgÌ Ë f for any choice of .

This intuition corresponds to a “type-erasure view” of what a term means:

XºÜ:XºÜ

for example, the polymorphic identify function  erases to the un-

ÜºÜ Ë typed identity function  , which maps an argument of any type to a

result of the same type Ë. XºÌ

2. A more operational intuition is that an element of 8 is a function mapping

fX 7! ËgÌ a type Ë to a concrete instance with type . This intuition corresponds to our definition of System F in Chapter 18, where the reduction of a type application is considered an actual step of the com-

putation.

9X¸Ì}

Similarly, there are two different ways of looking at an existential type ß :

9X¸Ì} fX 7! ËgÌ 1. The logical intuition is that an element of ß has type for some

type Ë.

144

January 15, 2000 19. EXISTENTIAL TYPES 145

9X¸Ì} Ë

2. The operational intuition is that an element of ß is a pair of a type and

fX 7! ËgÌ a term Ø of type . We will take an operational view of existentials in this chapter, since it provides a

closer analogy between existential packages and modules or abstract data types.

9X¸Ì}

Our concrete syntax for existential types (ß rather than the more standard XºÌ 9 ) reflects this analogy. As always, to understand existential types we need to know two things: how to build (or “introduce,” in the jargon of Section ??) elements of existential types,

and how to use (or “eliminate”) these values in computations.

9X=˸Ø} ß9X¸Ì} A value ß of type can be thought of as a simple module with 1 one (hidden) type component and one term component. The type Ë is often called the hidden representation type, or sometimes (to emphasize the connection with intuitionistic logic) the witness type of the package. As a simple example, the

package

Ô = ß9X=Æaظ ßa=5¸ f=Ü:Æaغ ×Ùcc´Üµ}}

has the existential type

ß9X¸ ßa:X¸ f:X!X}}:

a X

That is, the right-hand component of Ô is a record containing a field of type and

X!X X ÆaØ a field f of type , for some (namely ).

The same package Ô also has the type

ß9X¸ ßa:X¸ f:X!ÆaØ}};

f X X!ÆaØ

since its right-hand component is a record with fields a and of type and , ÆaØ for some X (namely ). This example shows that, in general, we can’t make an automatic decision about which existential type a given package belongs to: the programmer must specify which one is intended. The simplest way to do this is just to add an annotation to every package that explicitly gives its intended type.

So we’ll write

Ô½ = ß9X=Æaظ ßa=5¸ f=Ü:Æaغ ×Ùcc´Üµ}} a× ß9X¸ ßa:X¸ f:X!X}};

Á

Ô½ : ß9X¸ ßa:X¸f:X! X}} or: 1Obviously, we could generalize to many type/term components, but we’ll stick with just one of each to keep the notation tractable. The effect of multiple type components can be achieved by nesting single-type existentials, while the effect of multiple term components can be achieved by using a tuple or record as the right-hand component:

def

ß9X =Ë ¸ 9X =Ë ¸ Ø ¸ Ø } = ß9X =Ë ¸ ß9X =Ë ¸ ßØ ¸ Ø }}}

½ ½ ¾ ¾ ½ ¾ ½ ½ ¾ ¾ ½ ¾

January 15, 2000 19. EXISTENTIAL TYPES 146

Ô¾ = ß9X=Æaظ ßa=5¸ f=Ü:Æaغ ×Ùcc´Üµ}} a× ß9X¸ ßa:X¸ f:X!ÆaØ}};

Á

Ô¾ : ß9X¸ ßa:X¸f:X! ÆaØ}}

The type annotation introduced by a× is similar to the coercion construct intro- duced in Section ??, which allows any term to be annotated with its intended type. We are essentially requiring a single coercion as part of the concrete syntax of the package construct.

The complete typing rule for packages is as follows:

` Ø : fX 7! ÍgÌ

¾ ¾

(T-PACK)

` ß9X=Í¸Ø } a× ß9X¸Ì } : ß9X¸Ì }

¾ ¾ ¾ Of course, packages with different representation types can inhabit the same

existential type. For example:

Ô¿ = ß9X=Æaظ ¼} a× ß9X¸X};

Ô4 = ß9X=BÓÓи ØÖÙe} a× ß9X¸X};

Á

Ô¿ : ß9X¸ X}

Ô4 : ß9X¸ X}

Or, more usefully:

Ô5 = ß9X=Æaظ ßa=¼¸ f=Ü:Æaغ ×Ùcc´Üµ}} a× ß9X¸ ßa:X¸ f:X!ÆaØ}};

Ô6 = ß9X=BÓÓи ßa=ØÖÙe¸ f=Ü:BÓÓк ¼}} a× ß9X¸ ßa:X¸ f:X! ÆaØ}};

Á

Ô5 : ß9X¸ ßa:X¸f:X! ÆaØ}}

Ô6 : ß9X¸ ßa:X¸f:X! ÆaØ}}

19.1.1 Exercise [Quick check]: Here are three more variations on the same theme:

Ô7 = ß9X=Æaظ ßa=¼¸ f=Ü:Æaغ ×Ùcc´Üµ}} a× ß9X¸ ßa:X¸ f:X!X}};

Ô8 = ß9X=Æaظ ßa=¼¸ f=Ü:Æaغ ×Ùcc´Üµ}} a× ß9X¸ ßa:X¸ f:ÆaØ! X}};

Ô9 = ß9X=Æaظ ßa=¼¸ f=Ü:Æaغ ×Ùcc´Üµ}} a× ß9X¸ ßa:Æaظ f:ÆaØ! ÆaØ}};

Á

Ô7 : ß9X¸ ßa:X¸f:X! X}}

Ô8 : ß9X¸ ßa:X¸f:ÆaØ! X}}

Ô9 : ß9X¸ ßa:Æaظf:ÆaØ! ÆaØ}}

Ô6 ¾ In what ways are these less useful than Ô5 and ? (Solution on page ??.) A useful intuition for the existential elimination construct comes from the anal-

ogy with modules. If an existential package is a simple form of module, then pack- iÑÔÓÖØ age elimination is like an ÓÔeÒ or construct: it allows the components of the module to be used in some other part of the program, but holds the identity of the module’s type component abstract. This can be achieved with a kind of

pattern-matching binding:

` Ø : 9XºÌ ; X; Ü:Ì ` Ø : Ì

½ ½¾ ½¾ ¾ ¾

(T-UNPACK)

` ÐeØ ßX¸Ü}=Ø iÒ Ø : Ì

½ ¾ ¾ Ø

That is, if ½ is an expression that yields an existential package, then we can bind Ü

its type and term components to the pattern variables X and and use them in Ø computing ¾ .

For example, suppose that Ô has the following existential type:

January 15, 2000 19. EXISTENTIAL TYPES 147

Á

Ô : ß9X¸ ßa:X¸f:X! ÆaØ}}

Then the elimination expression

ÐeØ ßX¸Ü}=Ô iÒ ´Üºf ܺaµ;

Á

½ : ÆaØ

ܺf ܺa opens Ô and uses its components ( and ) to compute a numeric result. The

body of the elimination form is also permitted to use the type variable X,asinthe

following example:

ÐeØ ßX¸Ü}=Ô iÒ ´Ý:Xº ܺf ݵ ܺa;

Á

½ : ÆaØ

The fact that the package’s representation type is held abstract during the type-

Ø Ü

checking of the body ( ¾ ) means that the only operations allowed on are those Ì warranted by its “” ½ . In the present example, we are not allowed to

use ܺa concretely as a number:

ÐeØ ßX¸Ü}=Ô iÒ ×Ùcc´Üºaµ;

Á

EÖÖÓÖ: aÖgÙÑeÒØ Óf ×Ùcc i× ÒÓØ a ÒÙÑbeÖ

This restriction makes good sense, since we saw above that a package Ô with the BÓÓÐ given existential type might use either ÆaØ or as its representation type. There is another, more subtle, way in which typechecking of the existential

elimination construct may fail. In the rule T-UNPACK, the type variable X appears Ø

in the context in which ¾ ’s type is calculated, but does not appear in the context

Ì X of the rule’s conclusion. This means that the result type ¾ cannot contain free,

since any free occurrences of X will be out of scope in the conclusion. More oper- ationally, in terms of the nameless presentation of terms discussed in Section 5.1,

the T-UNPACK rule proceeds in three steps:

Ø ß9XºÌ } ½½

1. Check the subexpression ½ and ensure that it has an existential type .

X Ü:Ì Ø Ì

¾ ¾

2. Extend the context with and ½½ and check that has some type . Ì

3. Shift the indices of free variables in ¾ down by two, so that it makes sense

with respect to .

4. Return the resulting type as the type of the whole ÐeغººiÒººº expression.

X Ì

Clearly, if occurs free in ¾ , then the shifting step will yield a nonsensical type

containing free variables with negative indices; typechecking must fail at this point.

ÐeØ ßX¸Ü}=Ô iÒ Üºa;

Á

EÖÖÓÖ: ËcÓÔiÒg eÖÖÓÖ! January 15, 2000 19. EXISTENTIAL TYPES 148

The computation rule for existentials is straightforward: if the package subex-

pression has already been reduced to a concrete package, then we may substitute

X Ü Ø the components of the package for the variables and in the body ¾ :

In terms of the analogy with modules, this rule can be viewed as a kind of “link- Ü ing” operation, in which symbolic names (X and ) referring to the components of a separately compiled module are replaced by direct references to the actual con- tents of the module.

Since the type variable X is substituted away by this rule, the resulting pro- gram actually has concrete access to the package’s internals. This is just another example of a phenomenon we have seen several times: expressions can become “more typed” as computation proceeds, and in particular an ill-typed expression

can reduce to a well-typed one.

8 9 Existential types !

New syntactic forms

Ø ::= ... (terms...)

9X≠Ø} a× Ì

ß packing

ßX¸Ü}=Ø iÒ Ø ÐeØ unpacking

Ú ::= ... (values...)

9X≠Ú} a× Ì ß package value

Ì ::= ... (types...)

9X¸Ì}

ß existential type

¼

! Ø

New evaluation rules (Ø )

ÐeØ ßX¸Ü}=ß9X=Ì ¸Ú } a× Ì iÒ Ø

½¾ ½ ¾

½½ (E-PACKBETA)

! fX 7! Ì gfÜ 7! Ú gØ

½½ ½¾ ½¾

¼

Ø ! Ø ½¾

½¾ (E-PACK)

ß9X=Ì ¸Ø } a× Ì

½½ ½¾ ½

¼

! ß9X=Ì ¸Ø } a× Ì

½½ ½

½¾

¼

Ø ! Ø ½

½ (E-UNPACK)

ÐeØ ßX¸Ü}=Ø iÒ Ø

½ ¾

¼

iÒ Ø ! ÐeØ ßX¸Ü}=Ø

¾

½

` Ø : Ì

New typing rules ( )

` Ø : fX 7! ÍgÌ ¾

¾ (T-PACK)

` ß9X=Í¸Ø } a× ß9X¸Ì } : ß9X¸Ì }

¾ ¾ ¾

January 15, 2000 19. EXISTENTIAL TYPES 149

` Ø : 9XºÌ ; X; Ü:Ì ` Ø : Ì

½¾ ½¾ ¾ ¾

½ (T-UNPACK)

` ÐeØ ßX¸Ü}=Ø iÒ Ø : Ì

½ ¾ ¾

19.2 Data Abstraction with Existentials

Abstract Data Types For a more interesting example, here is a simple package defining an abstract data

type of (purely functional) counters.

cÓÙÒØeÖADÌ =

ß9CÓÙÒØeÖ = Æaظ

ßÒeÛ = ¼¸

geØ = i:Æaغ i¸

iÒc = i:Æaغ ×Ùcc´iµ}}

a× ß9CÓÙÒØeÖ¸

ßÒeÛ: CÓÙÒØeÖ¸

geØ: CÓÙÒØeÖ! Æaظ

iÒc: CÓÙÒØeÖ! CÓÙÒØeÖ}};

Á

cÓÙÒØeÖADÌ : ß9CÓÙÒØeÖ¸

ßÒeÛ:CÓÙÒØeÖ¸geØ:CÓÙÒØeÖ! ÆaظiÒc:CÓÙÒØeÖ! CÓÙÒØeÖ}}

The concrete representation of a counter is just a number. The package provides geØ three operations on counters: a constant ÒeÛ, a function for extracting a counter’s

current value, and a function iÒc for creating a new counter whose stored value is one more than the given counter’s. Having created the counter package, we next

open it, exposing the operations as the fields of a record cÓÙÒØeÖ:

ÐeØ ßCÓÙÒØeÖ¸cÓÙÒØeÖ}=cÓÙÒØeÖADÌ iÒ

cÓÙÒØeÖºgeØ ´cÓÙÒØeÖºiÒc cÓÙÒØeÖºÒeÛµ;

Á

½ : ÆaØ

If we organize our code so that the body of this ÐeØ contains the whole remainder

of the program, then this idiom

ÐeØ ßCÓÙÒØeÖ¸cÓÙÒØeÖ} =

<Öe×Ø Óf ÔÖÓgÖaÑ> cÓÙÒØeÖ

has the effect of declaring a fresh type CÓÙÒØeÖ and a variable of type

:CÓÙÒØeÖ!ÆaظiÒc: CÓÙÒØeÖ!CÓÙÒØeÖ} ßÒeÛ:CÓÙÒØeÖ¸geØ . It is instructive to compare the above with a more standard abstract declaration, such as might be found in a program in Ada [oD80] or Clu [LAB · 81]:

January 15, 2000 19. EXISTENTIAL TYPES 150

ADÌ cÓÙÒØeÖ =

ØÝÔe CÓÙÒØeÖ

ÖeÔÖe×eÒØaØiÓÒ ÆaØ

ÓÔeÖaØiÓÒ×

ßÒeÛ = ¼

: CÓÙÒØeÖ¸

geØ = i:Æaغ i

: CÓÙÒØeÖ! Æaظ

iÒc = i:Æaغ ×Ùcc´iµ}

: CÓÙÒØeÖ! CÓÙÒØeÖ};

cÓÙÒØeÖºgeØ ´cÓÙÒØeÖºiÒc cÓÙÒØeÖºÒeÛµ;

The version using existential types is somewhat harder to read, compared to the syntactically sugared second version, but otherwise the two programs are essen- tially identical.

Note that we can substitute an alternative implementation of the CÓÙÒØeÖ ADT—

for example, one where the internal representation is a record containing a ÆaØ

rather than just a single ÆaØ

cÓÙÒØeÖADÌ =

ß9CÓÙÒØeÖ = ßÜ:ÆaØ}¸

ßÒeÛ = ßÜ=¼}¸

geØ = i:ßÜ:ÆaØ}º iºÜ¸

iÒc = i:ßÜ:ÆaØ}º ßÜ=×Ùcc´iºÜµ}}}

a× ß9CÓÙÒØeÖ¸

ßÒeÛ: CÓÙÒØeÖ¸

geØ: CÓÙÒØeÖ! Æaظ

iÒc: CÓÙÒØeÖ! CÓÙÒØeÖ}};

Á

cÓÙÒØeÖADÌ : ß9CÓÙÒØeÖ¸

ßÒeÛ:CÓÙÒØeÖ¸geØ:CÓÙÒØeÖ! ÆaظiÒc:CÓÙÒØeÖ! CÓÙÒØeÖ}} in complete confidence that the whole program will remain typesafe, since we are

guaranteed that the rest of the program cannot access instances of CÓÙÒØeÖ except iÒc using geØ and . This is the essence of data abstraction by information hiding.

In the body of the program, the type name CÓÙÒØeÖ can be used just like the base types built into the language. We can define functions that operate on coun-

ters:

ÐeØ ßCÓÙÒØeÖ¸cÓÙÒØeÖ}=cÓÙÒØeÖADÌ

ÐeØ addØhÖee = c:CÓÙÒØeÖº

cÓÙÒØeÖºiÒc ´cÓÙÒØeÖºiÒc ´cÓÙÒØeÖºiÒc cµµ

cÓÙÒØeÖºgeØ ´addØhÖee cÓÙÒØeÖºÒeÛµ;

January 15, 2000 19. EXISTENTIAL TYPES 151

Á

¿ : ÆaØ

We can even define new abstract data types whose representation involves coun- ters. For example, the following program defines an ADT of flip-flops, using a

counter as the (not very efficient) representation type:

ÐeØ ßCÓÙÒØeÖ¸cÓÙÒØeÖ} =

ß9CÓÙÒØeÖ = Æaظ

ßÒeÛ = ¼¸

geØ = i:Æaغ i¸

iÒc = i:Æaغ ×Ùcc´iµ}}

a× ß9CÓÙÒØeÖ¸

ßÒeÛ: CÓÙÒØeÖ¸

geØ: CÓÙÒØeÖ! Æaظ

iÒc: CÓÙÒØeÖ! CÓÙÒØeÖ}}

ÐeØ ßFÐiÔFÐÓÔ¸fÐiÔfÐÓÔ} =

ß9FÐiÔFÐÓÔ = CÓÙÒØeÖ¸

ßÒeÛ = cÓÙÒØeÖºÒeÛ¸

Öead = c:CÓÙÒØeÖº i×eÚeÒ ´cÓÙÒØeÖºgeØ cµ¸

ØÓggÐe = c:CÓÙÒØeÖº cÓÙÒØeÖºiÒc c¸

Öe×eØ = c:CÓÙÒØeÖº cÓÙÒØeÖºÒeÛ}}

a× ß9FÐiÔFÐÓÔ¸

ßÒeÛ: FÐiÔFÐÓÔ¸

Öead: FÐiÔFÐÓÔ! BÓÓи

ØÓggÐe: FÐiÔFÐÓÔ! FÐiÔFÐÓÔ¸

Öe×eØ: FÐiÔFÐÓÔ! FÐiÔFÐÓÔ}}

fÐiÔfÐÓÔºÖead ´fÐiÔfÐÓÔºØÓggÐe ´fÐiÔfÐÓÔºØÓggÐe fÐiÔfÐÓÔºÒeÛµµ;

Á

faÐ×e : BÓÓÐ

19.2.1 Exercise [Recommended]: Follow the model of the above example to de-

ÔÙ×h ÔÓÔ

fine an of stacks of numbers, with operations ÒeÛ, , , and Äi×Ø i×eÑÔØÝ. Use the type introduced in Exercise ?? as the underlying representa- tion. Write a simple main program that creates a stack, pushes a couple of numbers onto it, pops off the top element, and returns it.

This exercise is best done on-line. Use the checker named “eÚeÖÝØhiÒg” and eÚeÖÝØhiÒg copy the contents of the file Øe×غf from the directory (which contains

definitions of the Äi×Ø constructor and associated operations) to the top of your

own input file. ¾ January 15, 2000 19. EXISTENTIAL TYPES 152

Existential Objects The sequence of “pack then open” that we saw in the last section is the hallmark of ADT-style programming using existential packages. A package defines an abstract type and its associated operations, and each package is opened immediately after it is built, binding a type variable for the abstract type and exposing the ADT’s op- erations abstractly, with this variable in place of the concrete representation type. Existential types can also be used to model other common types of data abstrac- tion. In this section, we show how a simple form of objects can be understood in terms of a different idiom based on existentials. We will again use simple counters as our running example, as we did both in the previous section on existential ADTs and in our previous encounter with objects, in Chapter 14. Unlike the counters of Chapter 14, however, the counter ob-

jects in this section will be purely functional: sending the message iÒc to a counter will not change its internal state in-place, but rather will return a fresh counter ob- ject with incremented internal state.

A counter object, then, will comprise two basic components: a number (its in- iÒc ternal state), and a pair of methods, geØ and , that can be used to query and update the state. We also need to ensure that the only way that the state of a counter object can be queried or updated is by using one of its two methods. This can be accomplished by wrapping the state and methods in an existential package, abstracting the type of the internal state. For example, a counter object holding the

value 5 might be written

c = ß9X = Æaظ

ß×ØaØe = 5¸

ÑeØhÓd× = ßgeØ = Ü:Æaغ ܸ

iÒc = Ü:Æaغ ×Ùcc´Üµ}}}

a× CÓÙÒØeÖ;

where:

CÓÙÒØeÖ = ß9X¸ ß×ØaØe:X¸ ÑeØhÓd×: ßgeØ:X! Æaظ iÒc:X!X}}};

To use a method of a counter object, we will need to open it up and apply ×ØaØe the appropriate element of its ÑeØhÓd× to its field. For example, to get the

current value of c we can write:

ÐeØ ßX¸bÓdÝ} = c iÒ

bÓdݺÑeØhÓd׺geØ´bÓdݺ×ØaØeµ ;

Á

5 : ÆaØ

More generally, we can define a little function that “sends the geØ message” to any

counter:

×eÒdgeØ = c:CÓÙÒØeÖº

ÐeØ ßX¸bÓdÝ} = c iÒ bÓdݺÑeØhÓd׺geØ´bÓdݺ×ØaØeµ;

January 15, 2000 19. EXISTENTIAL TYPES 153

Á

×eÒdgeØ : CÓÙÒØeÖ ! ÆaØ

Invoking the iÒc method of a counter object is a little more complicated. If we

simply do the same as for geØ, the typechecker complains

ÐeØ ßX¸bÓdÝ} = c iÒ

bÓdݺÑeØhÓd׺iÒc´bÓdݺ×ØaØeµ ;

Á

EÖÖÓÖ: ËcÓÔiÒg eÖÖÓÖ! ÐeØ because the type variable X appears free in the type of the body of the . Indeed,

what we’ve written doesn’t make intuitive sense either, since the result of the iÒc method is a “bare” internal state, not an object. To satisfy both the typechecker and

our informal understanding of what invoking iÒc should do, we must take this fresh internal state and “repackage” it as a counter object, using the same record

of methods and the same internal state type as in the original object:

c½ = ÐeØ ßX¸bÓdÝ} = c iÒ

ß9X = X¸

ß×ØaØe = bÓdݺÑeØhÓd׺iÒc´bÓdݺ×ØaØeµ¸

ÑeØhÓd× = bÓdݺÑeØhÓd×}}

a× CÓÙÒØeÖ;

More generally, to “send the iÒc message” to an arbitrary counter object, we can

write:

×eÒdiÒc = c:CÓÙÒØeÖº

ÐeØ ßX¸bÓdÝ} = c iÒ

ß9X = X¸

ß×ØaØe = bÓdݺÑeØhÓd׺iÒc´bÓdݺ×ØaØeµ¸

ÑeØhÓd× = bÓdݺÑeØhÓd×}}

a× CÓÙÒØeÖ;

Á

×eÒdiÒc : CÓÙÒØeÖ ! CÓÙÒØeÖ

More complex operations on counters can be implemented in terms of these two

basic operations:

addØhÖee = c:CÓÙÒØeÖº ×eÒdiÒc ´×eÒdiÒc ´×eÒdiÒc cµµ;

Á

addØhÖee : CÓÙÒØeÖ ! CÓÙÒØeÖ CÓÙÒØeÖ

19.2.2 Exercise: Implement FÐiÔFÐÓÔ objects with objects as their internal ¾ representation type, following the model of the FÐiÔFÐÓÔ ADT in Section 19.2. January 15, 2000 19. EXISTENTIAL TYPES 154

Objects vs. ADTs What we have seen in Section 19.2 falls significantly short of a full-blown model

of object-oriented programming. Many of the features that we saw in Chapter 14, ×ÙÔeÖ including subtyping, classes, inheritance, and recursion through ×eÐf and , are missing here. We will come back to modeling these features in later chapters, when we have added a few necessary refinements to our modeling language. But even for the simple objects we have developed so far, there are several interesting comparisons to be made with ADTs. At the coarsest level, the two programming idioms fall at opposite ends of a spectrum: when programming with ADTs, packages are opened immediately after they are built; on the other hand, when packages are used to model objects they are kept closed as long as possible—until the moment when they must be opened so that one of the methods can be applied to the internal state. A consequence of this difference is that the “abstract type” of counters refers to different things in the two styles. In an ADT-style program, the counter val-

ues manipulated by client code such as addØhÖee are elements of the underlying representation type (e.g., simple numbers). In an object-style program, a counter

value is a whole package—not only a number, but also the implementations of iÒc

the geØ and methods. This stylistic difference is reflected in the fact that, in ÐeØ the ADT style, the type CÓÙÒØeÖ is a bound type variable introduced by the

construct, while in the object style CÓÙÒØeÖ abbreviates the whole existential type

9X¸ ß×ØaØe:X¸ ÑeØhÓd×: ßgeØ:X!ÆaظiÒc:X!X}}} ß . Thus:

¯ All the counter values generated from the counter ADT are elements of the same internal representation type; there is a single implementation of the counter operations that works on this internal representation.

¯ Each counter object, on the other hand, carries its own representation type and its own set of methods that work for this representation type.

19.2.3 Exercise: In what ways do the classes found in mainstream object-oriented languages like C++ and Java resemble the simple object types discussed here? In

what ways do they resemble ADTs? ¾

19.3 Encoding Existentials

The encoding of pairs as a polymorphic type in Exercise 18.4.5 suggests a similar encoding for existential types in terms of universal types, using the intuition that an element of an existential type is a pair of a type and a value:

def

ß9X¸Ì} = 8Yº ´8Xº Ì!Yµ ! Y:

That is, an existential package is thought of as a data value that, given a result type and a “continuation,” calls the continuation to yield a final result. The continuation

January 15, 2000 19. EXISTENTIAL TYPES 155 Ì takes two arguments—a type X and a value of type —and uses them in computing the final result. Given this encoding of existential types, the encoding of the packaging and

unpackaging constructs is essentially forced. To encode a package

ß9X=˸Ø} a× ß9X¸Ì}

Yº ´8Xº Ì!Yµ ! Y we must exhibit a value of type 8 . This type begins with a universal quantifier, the body of which is an arrow. An element of this type should therefore begin with two abstractions:

def

ß9X=˸ÐØ} a× ß9X¸Ì} = Yº f:´8XºÌ!Yµº ººº

To complete the job, we need to return a result of type Y; clearly, the only way to Ë do this is to apply f to some appropriate arguments. First, we supply the type (this is a natural choice, being the only type we have lying around at the moment):

def

ß9X=˸Ø} a× ß9X¸Ì} = Yº f:´8XºÌ!Yµº f [Ë] ººº

[Ë] fX 7! Ëg´Ì!Yµ ´fX 7! Ëg̵!Y

Now, the type application f has type , i.e., .We

fX 7! ËgÌ can thus supply Ø (which, by rule T-PACK, has type ) as the next argument:

def

ß9X=˸Ø} a× ß9X¸Ì} = Yº f:´8XºÌ!Yµº f [Ë] Ø

[Ë] Ø Y The type of the whole application f is now , as required. To encode the unpacking construct

def

ÐeØ ßX¸Ü}=Ø iÒ Ø = ººº

½ ¾ Ø

we proceed as follows. First, the typing rule T-UNPACK tells us that ½ should

ß9X¸Ì } Ø Ì

¾ ¾

have some type ½½ , that should have type (under an extended context

X Ü:Ì Ì ÐeغººiÒººº ¾ binding and ½½ ), and that is the type we expect for the whole

expression.2 As in the Church encodings in Section 18.4, the intuition here is that

9X=˸Ø} the introduction form (ß ) is encoded as an active value that “performs its

own elimination.” So the encoding of the elimination form here should simply Ø

take the existential package ½ and apply it to enough arguments to yield a result Ì of the desired type ¾ :

def

ÐeØ ßX¸Ü}=Ø iÒ Ø = Ø ººº

½ ¾ ½ Ø

The first argument to ½ should be the desired result of the whole expression, i.e., Ì

¾ :

def

ÐeØ ßX¸Ü}=Ø iÒ Ø = Ø [Ì ] ººº

½ ¾ ½ ¾

2Strictly speaking, the fact that the translation requires these extra bits of type information not present in the syntax of terms means that what we are translating is actually typing derivations, not terms.

January 15, 2000 19. EXISTENTIAL TYPES 156

Ø [Ì ] ´8Xº Ì!Ì µ ! Ì

¾ ¾ ¾

Now, the application ½ has type . That is, if we can now

´8XºÌ!Ì µ

supply another argument of type ¾ , we will be finished. Such an argu-

Ø X Ü ment can be obtained by abstracting the body ¾ on the variables and :

def

ÐeØ ßX¸Ü}=Ø iÒ Ø = Ø [Ì ] ´Xº Ü:Ì º Ø µ:

½ ¾ ½ ¾ ½½ ¾

This finishes the encoding.

19.3.1 Exercise: What must we prove to show that our encoding of existentials is

correct? ¾

19.3.2 Exercise [Recommended]: Take a blank piece of paper and, without looking

at the above encoding, regenerate it from scratch. ¾

19.3.3 Exercise: Can universal types be encoded in terms of existential types? ¾

19.4 Implementation

ØÝÔe ØÝ =

ººº

| ÌÝËÓÑe Óf ×ØÖiÒg ¶ ØÝ

ØÝÔe ØeÖÑ =

ººº

| ÌÑÈack Óf iÒfÓ ¶ ×ØÖiÒg ¶ ØÝ ¶ ØeÖÑ ¶ ØÝ

| ÌÑÍÒÔack Óf iÒfÓ ¶ ×ØÖiÒg ¶ ×ØÖiÒg ¶ ØeÖÑ ¶ ØeÖÑ

19.5 Historical Notes

The correspondence between ADTs and existential types was first developed by Mitchell and Plotkin [MP88]. (They also noticed the correspondance with objects.) Chapter 20

Bounded Quantification

Many of the interesting problems in type systems arise from the combination of features that, in themselves, may be quite simple. In this chapter, we encounter our first substantial example: a system that mixes subtyping with polymorphism. The most basic combination of these features is actually quite straightforward.

We simply add to the subtyping relation a rule for comparing quantified types:

Ë <: Ì

8XºË <: 8XºÌ We consider here a more interesting combination, in which the syntax, typing, and subtyping rules for universal quantifiers are actually refined to take subtyping into account. The resulting notion of bounded quantification substantially increases both the expressive power of the system and its metatheoretic complexity.

20.1 Motivation

To see why we might want to combine subtyping and polymorphism in this more

intimate manner, consider the identity function on records with a numeric field a:

f = Ü:ßa:ÆaØ}º Ü;

Á

f : ßa:ÆaØ} ! ßa:ÆaØ}

If we define a record of this form

Öa = ßa=¼}; Öa then we can apply f to (in any of the systems that we have seen), yielding a

record of the same form.

´f Öaµ;

Á

ßa=¼} : ßa:ÆaØ}

157

January 15, 2000 20. 158

a b

If we define a larger record Öab with two fields, and ,

Öab = ßa=¼¸ b=ØÖÙe}; Öab we can also apply f to , using the rule of subsumption introduced in Chap-

ter 13.

´f Öabµ;

Á

ßa=¼¸ b=ØÖÙe} : ßa:ÆaØ}

However, the type of the result has only the field a, which means that a term like

Öabµºb Öab ´f will be judged ill typed. In other words, by passing through the

identity function, we have lost the ability to access its b field!

Using the polymorphism of System F, we can write f in a different way:

fÔÓÐÝ = Xº Ü:Xº Ü;

Á

fÔÓÐÝ : 8Xº X ! X Öab The application of fÔÓÐÝ to (and an appropriate type argument) yields the

desired result:

´fÔÓÐÝ [ßa:Æaظ b:BÓÓÐ}] Öabµ;

Á

ßa=¼¸ b=ØÖÙe} : ßa:Æaظ b:BÓÓÐ}

But in making the type of Ü into a variable, we have given up some information f that f might have wanted to use. For example, suppose we intend that return a

pair of its original argument and the numeric successor of its a field.

f¾ = Ü:ßa:ÆaØ}º ßÓÖig=ܸ a×Ùcc=×Ùcc´Üºaµ};

Á

f¾ : ßa:ÆaØ} ! ßÓÖig:ßa:ÆaØ}¸ a×Ùcc:ÆaØ}

Öa Öab b

Again, we can apply f¾ to both and , losing the field in the second case.

´f¾ Öaµ;

Á

ßÓÖig=ßa=¼}¸ a×Ùcc=½} : ßÓÖig:ßa:ÆaØ}¸ a×Ùcc:ÆaØ}

´f¾ Öabµ;

Á

ßÓÖig=ßa=¼¸b=ØÖÙe}¸ a×Ùcc=½} : ßÓÖig:ßa:ÆaØ}¸ a×Ùcc:ÆaØ}

But this time polymorphism offers us no solution. If we replace the type of Ü by

Ü a a variable X as before, we lose the constraint that must have an field, which is

required to compute the a×Ùcc field of the result.

f¾ÔÓÐÝ = Xº Ü:Xº ßÓÖig=ܸ a×Ùcc=×Ùcc´Üºaµ};

Á

EÖÖÓÖ: EÜÔecØed ÖecÓÖd ØÝÔe

The fact about the operational behavior of f¾ that we want to express in its type is:

January 15, 2000 20. BOUNDED QUANTIFICATION 159

Ê a f¾ takes an argument of any record type that includes a numeric

field and returns as its result a record containing a field of type Ê and a

field of type ÆaØ.

We can use the subtype relation to express this concisely as follows:

Ê ßa:ÆaØ}

f¾ takes an argument of any subtype of the type and returns ÆaØ a record containing a field of type Ê and a field of type .

This intuition can be formalized by introducing a subtyping constraint on the f¾ÔÓÐÝ

bound variable X of .

f¾ÔÓÐÝ = X<:ßa:ÆaØ}º Ü:Xº ßÓÖig=ܸ a×Ùcc=×Ùcc´Üºaµ};

Á

f¾ÔÓÐÝ : 8X<:ßa:ÆaØ}º X ! ßÓÖig:X¸ a×Ùcc:ÆaØ}

This interaction of subtyping and polymorphism, called bounded quantification, : leads us to a type system commonly called System F< (“F sub”), which is the topic of this chapter.

20.2 Definitions : We form System F< by combining the types and terms of System F with the sub- type relation from Chapter 13 and refining universal quantifiers with subtyping constraints on their bound variables. When we define the subtyping rule for these bounded quantifiers, there will actually be two choices: a more tractable but less flexible rule called the kernel rule and a more expressive full subtyping rule, which will turn out to raise some unexpected difficulties when we come to de-

signing typechecking algorithms. : Kernel F < Since type variables now have associated bounds (just as ordinary variables have associated types), we must keep track of them during both subtyping and type- checking. We change the type bindings in contexts to include an upper bound for each type variable, and add contexts to all the rules in the subtype relation.

These bounds will be used during subtyping to justify steps of the form “the type Ì

variable X is a subtype of the type because we assumed it was.”

X<:Ì ¾

(S-TVAR)

` X <: Ì

20.2.1 Exercise [Quick check]: Exhibit a subtyping derivation showing that

B<:ÌÓÔ; X<:B; Y<:X ` B!Y <: X!B: ¾ January 15, 2000 20. BOUNDED QUANTIFICATION 160

Next, we introduce bounded universal types, extending the syntax and typ- ing rules for ordinary universal types in the obvious way. The only rule where the extension is not completely obvious is the subtyping rule for quantified types, S-ALL. We give here the simpler variant, called the kernel subtyping rule for universal quantifiers, in which the bounds of the two quantifiers being compared

must be identical. (The term “kernel” comes from Cardelli and Wegner’s original :

paper [CW85], where this variant of F < was called Kernel Fun.)

X<:Ì ¾

(S-TVAR)

` X <: Ì : For easy reference, here is the complete definition of kernel F < , with differences from previous systems highlighted:

k

F ! 8 <:

<: : Bounded quantification bq

Syntax

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø

Ø application

X <:Ì ºØ

 type abstraction [Ì] Ø type application

Ú ::= (values...)

Ü:̺Ø

 abstraction value

X <:Ì ºØ  type abstraction value

Ì ::= (types...)

X type variable

ÌÓÔ maximum type

Ì type of functions

X <:Ì ºÌ 8 universal type

::= (contexts...)

; empty context Ü:Ì

; term variable binding

X <:Ì

; type variable binding

¼

! Ø

Evaluation (Ø )

´Ü:Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾ ½

January 15, 2000 20. BOUNDED QUANTIFICATION 161

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

´X <:Ì ºØ µ [Ì ] ! fX 7! Ì gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA2)

¼

Ø ! Ø ½

½ (E-TAPP)

¼

Ø [Ì ] ! Ø [Ì ]

½ ¾ ¾

½

` Ë <: Ì

Subtyping ( )

` Ë <: Ë

(S-REFL)

` Ë <: Í ` Í <: Ì

(S-TRANS)

` Ë <: Ì

` Ë <: ÌÓÔ

(S-TOP)

X<:Ì ¾

(S-TVAR)

` X <: Ì

` Ì <: Ë ` Ë <: Ì

½ ½ ¾ ¾

(S-ARROW)

` Ë !Ë <: Ì !Ì

½ ¾ ½ ¾

; X<:Í ` Ë <: Ì

¾ ¾

½ (S-ALL)

`8X<:Í ºË <: 8X<:Í ºÌ

½ ¾ ½ ¾

` Ø : Ì

Typing ( )

Ü:Ì ¾

(T-VAR)

` Ü : Ì

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

; X <:Ì ` Ø : Ì

½ ¾ ¾

(T-TABS)

` X <:Ì ºØ : 8X <:Ì ºÌ

½ ¾ ½ ¾

` Ø : 8X <:Ì ºÌ ` Ì <: Ì

½ ½½ ½¾ ¾ ½½

(T-TAPP)

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾

` Ø : Ë ` Ë <: Ì

(T-SUB)

` Ø : Ì

January 15, 2000 20. BOUNDED QUANTIFICATION 162 :

Full F< : In kernel F< , two quantified types can only be compared if their upper bounds are identical. If we think of quantifiers as a kind of arrow types (since they classify functions from types to terms), then the kernel rule corresponds to a “covariant” version of the subtyping rule for arrows, in which the domain of an arrow type is

not allowed to vary in subtypes:

Ë <: Ì

¾ ¾

Í!Ë <: Í!Ì

¾ ¾ This restriction feels rather unnatural, both for arrows and for quantifiers. Car- rying the analogy a little further, we can allow the “left-hand side” of bounded quantifiers to vary (contravariantly) during subtyping:

f

F ! 8 <:

<: : “Full” bounded quantification bq full

` Ë <: Ì

New subtyping rules ( )

` Ì <: Ë ; X<: Ì ` Ë <: Ì

½ ½ ½ ¾ ¾

(S-ALL)

`8X<: Ë ºË <: 8X<: Ì ºÌ

½ ¾ ½ ¾ :

Intuitively, the “full F< ” quantifier subtyping rule can be understood as fol-

Ì = 8X<:Ì ºÌ ¾

lows. A type ½ describes a collection of polymorphic values (func-

Ì Ì Ì

¾ ½

tions from types to values), each mapping subtypes of ½ to instances of .If

Ë Ì Ë = 8X<:Ë ºË

½ ¾ is a subtype of ½ , then the domain of is smaller than that of ,so

Ë is a stronger constraint and describes a smaller collection of polymorphic values.

Moreover, if, for each type Í that is an acceptable argument to the functions in both

Í <: Ì Í

collections (i.e., one that satisfies the more stringent requirement ½ ), the -

Ë Í Ì Ë ¾ instance of ¾ is a subtype of the -instance of , then is a “pointwise stronger” constraint and again describes a smaller collection of polymorphic values. The system with just the kernel subtyping rule for quantified types is called

k

F

<:

Kernel F (or <: ). The same system with the full quantifier subtyping rule is called

f

F

<:

: <: Full F< (or ). The bare name F refers ambiguously to both systems.

20.2.2 Exercise [Quick check]: Give a couple of examples of pairs of types that are

¾

: <: related by the subtype relation of full F < but are not subtypes in kernel F .

20.2.3 Exercise [Challenging]: Can you find any useful examples with this prop-

erty? ¾ January 15, 2000 20. BOUNDED QUANTIFICATION 163

20.3 Examples : We now present some simple examples of programming in F< . More sophisticated uses of bounded quantification will appear in later chapters.

Encoding Products In Exercise ??, we gave the following encoding of pairs in System F. The elements

of the type

ÈaiÖ Ì Ì = 8Xº ´Ì !Ì !Xµ ! X;

½ ¾ ½ ¾

Ì Ì ÔaiÖ f×Ø ¾ correspond to pairs of ½ and . The constructor and the destructors and

×Òd were defined as follows:

ÔaiÖ = Xº Yº Ü:Xº Ý:Yº

´ ʺ Ô:X! Y!ʺ Ô Ü Ý

a× ÈaiÖ X Yµ;

f×Ø = Xº Yº Ô: ÈaiÖ X Yº

Ô [X] ´Ü:Xº Ý:Yº ܵ;

×Òd = Xº Yº Ô: ÈaiÖ X Yº

Ô [Y] ´Ü:Xº Ý:Yº ݵ;

: <: Of course, the same encoding can be used in F< , since F contains all the features of System F. What is interesting, though, is that this encoding also has some natural

subtyping properties. In fact, the expected subtyping rule for pairs

` Ë <: Ì ` Ë <: Ì

½ ½ ¾ ¾

` ÈaiÖ Ë Ë <: ÈaiÖ Ì Ì

½ ¾ ½ ¾ follows directly from the encoding.

20.3.1 Exercise [Quick check]: Show this. ¾

Encoding Records It is interesting to notice that records and record types—including subtyping— can actually be encoded in the pure calculus. The encoding presented here was

discovered by Cardelli [Car92]. We begin by defining flexible tuples as follows:

Ò  ¼ Ì Ì Ò 20.3.2 Definition: For each and types ½ through , let

def

i¾½::Ò

ßÌ } = ÈaiÖ Ì ´ÈaiÖ Ì ººº ´ÈaiÖ Ì ÌÓÔµºººµ:

i ½ ¾ Ò

ß} = ÌÓÔ Ø Ø Ò In particular, . Similarly, for terms ½ through , let

def

i¾½::Ò

ßØ } ÔaiÖ Ø ´ÔaiÖ Ø ººº ´ÔaiÖ Ø ØÓÔµºººµ;

=

i ½ ¾ Ò

January 15, 2000 20. BOUNDED QUANTIFICATION 164 ØÓÔ

where we elide the type arguments to ÔaiÖ, for the sake of brevity. (Recall that غÒ

is just some element of ÌÓÔ.) The projection (again eliding type arguments) is:

f×Ø´ ×Òd´×Òdººº´×Òd صºººµ ¾

| ßÞ }

¹½ Ò times From this abbreviation, we immediately obtain the following rules for subtyping

and typing.

i¾½::Ò

` Ë <: Ì

i i

i¾½::Ò·k i¾½::Ò

` ßË } <: ßÌ }

i i

i¾½::Ò

` Ø : Ì

i i

i¾½::Ò i¾½::Ò

` ßØ } : ßÌ }

i i

i¾½::Ò

` Ø : ßÌ }

i

` غi : Ì i

Now, let Ä be a countable set of labels, with a fixed total ordering given by the

Æ ! Ä

bijective function label-with-index : . We define records as follows:

Ä Ä Ë Ð ¾ Ä

20.3.3 Definition: Let be a finite subset of and let Ð be a type for each . Ä

Let Ñ be the maximal index of any element of , and

¬

´iµ=Ð ¾ Ä Ë

Ð if label-with-index

^

Ë =

i

´iµ ¾= Ä:

ÌÓÔ if label-with-index

i¾½::Ñ

оÄ

^

ßÐ:Ë } ßË Ø }

Ð Ð

The record type is defined as the flexible tuple i . Similarly, if

: Ä

is a term for each Ð , then

¬

´iµ=Ð ¾ Ä Ø

i if label-with-index

^

Ø =

i

´iµ ¾= Ä:

ØÓÔ if label-with-index

i¾½::Ñ

оÄ

^

} } ßÐ=Ø ßØ ØºÐ

Ð i

The record value is i . The projection is just the tuple projec- ¾ tion غi.

This encoding validates the expected rules for typing and subtyping:

i¾½::Ò i¾½::Ò·k

} } <: ßÐ :Ì ` ßÐ :Ì

i i i

i (S-RCD-WIDTH)

i ` Ë <: Ì i for each i

(S-RCD-DEPTH)

i¾½::Ò i¾½::Ò

` ßÐ :Ë } <: ßÐ :Ì }

i i i i January 15, 2000 20. BOUNDED QUANTIFICATION 165

Church Encodings with Subtyping : As a last simple illustration of the expressiveness of F< , let’s take a look at what happens when we add bounded quantification to the encoding of Church Numer- als in System F that we saw in Section 18.4. The original polymorphic type of

church numerals was:

CÆaØ = 8Xº ´X!Xµ ! X ! X;

The intuitive reading of this type was: “Tell me a result type Ì and give me a

Ì Ì function on Ì and an element of , and I’ll give you back another element of

formed by iterating the function you gave me Ò times over the base value you gave.”

We can generalize this by adding two bounded quantifiers and refining the Þ

types of the parameters × and .

ËÆaØ = 8X<:ÌÓÔº 8Ë<:Xº 8Z<:Xº ´X!˵ ! Z ! X;

Intuitively, this type can be read as follows: “Give me a generic result type Ì and

Z Ì

two subtypes Ë and . Then give me a function that maps from the whole set into

Z Ì the subset Ë and an element of the special set , and I’ll return you an element of formed in the same way as before.” To see why this is an interesting generalization, consider this slightly different

type:

ËZeÖÓ = 8X<:ÌÓÔº 8Ë<:Xº 8Z<:Xº ´X! ˵ ! Z ! Z; ËÆaØ Although ËZeÖÓ has almost the same form as , it says something much stronger

about the behavior of its elements, since it promises that its result will be an ele-

Ì Z ment of Z, not just of . In fact, there is just one way that an element of could be

returned—namely by yielding just Þ itself. In other words, the value

×ÞeÖÓ = ´Xº Ë<:Xº Z<:Xº ×:X!˺ Þ:Zº Þµ a× ËZeÖÓ;

Á

×ÞeÖÓ : ËZeÖÓ

is the only inhabitant of the type ËZeÖÓ. On the other hand, the similar type

ËÈÓ× = 8X<:ÌÓÔº 8Ë<:Xº 8Z<:Xº ´X!˵ ! Z ! Ë;

has more inhabitants; for example,

×ÓÒe = ´Xº Ë<:Xº Z<:Xº ×:X!˺ Þ:Zº × Þµ a× ËÈÓ×;

×ØÛÓ = ´Xº Ë<:Xº Z<:Xº ×:X!˺ Þ:Zº × ´× Þµµ a× ËÈÓ×;

×ØhÖee = ´Xº Ë<:Xº Z<:Xº ×:X!˺ Þ:Zº × ´× ´× Þµµµ a× ËÈÓ×;

and so on.

ËÈÓ× ËÆaØ

Moreover, notice that ËZeÖÓ and are both subtypes of (Exercise:

: ËÆaØ ×ÓÒe : ËÆaØ ×ØÛÓ : ËÆaØ check this), so we also have ×ÞeÖÓ , , , etc. Finally, we can similarly refine the typings of operations defined on church numerals. For example, the type system is capable of detecting that the successor function always returns a positive number:

January 15, 2000 20. BOUNDED QUANTIFICATION 166

××Ùcc = Ò:ËÆaغ

´Xº Ë<:Xº Z<:Xº ×:X!˺ Þ:Zº

× ´Ò [X] [Ë] [Z] × Þµµ

a× ËÈÓ×;

Á

××Ùcc : ËÆaØ ! ËÈÓ×

Similarly, by refining the types of its parameters, we can write the function ÔÐÙ× in

!ËZeÖÓ!ËÈÓ×

such a way that the typechecker gives it the refined type ËÈÓ× .

×ÔÐÙ×ÔÞ = Ò:ËÈÓ׺ Ñ:ËZeÖÓº

´Xº Ë<:Xº Z<:Xº ×:X! ˺ Þ:Zº

Ò [X] [Ë] [Z] × ´Ñ [X] [Ë] [Z] × Þµµ

a× ËÈÓ×;

Á

×ÔÐÙ×ÔÞ : ËÈÓ× ! ËZeÖÓ ! ËÈÓ×

ËÈÓ×!ËÈÓ×!ËÈÓ×

20.3.4 Exercise: Write a similar version of ÔÐÙ× that has type .

!ËÆaØ!ËÆaØ ¾ Write one that has type ËÆaØ .

The previous example and exercise raise an interesting point: obviously, we

don’t want to have several different versions of ÔÐÙ× lying around and have to de- cide which to apply based on the expected types of its arguments: we want to have

a single version of ÔÐÙ× whose type contains all these possibilities—something like

ÔÐÙ× : ËZeÖÓ! ËZeÖÓ! ËZeÖÓ

^ ËÆaØ! ËÈÓ×! ËÈÓ×

^ ËÈÓ×! ËÆaØ! ËÈÓ×

^ ËÆaØ! ËÆaØ! ËÆaØ

The desire to support this kind of overloading has led to the study of systems with intersection types.

20.3.5 Exercise [Recommended]: Generalize the type CBÓÓÐ of Church Booleans

from Section 18.4 in a similar way by defining a type ËBÓÓÐ and two subtypes

ËFaÐ×e ÒÓØfØ ËFaÐ×e!ËÌÖÙe

ËÌÖÙe and . Write a function with type and a similar

ËÌÖÙe!ËFaÐ×e ¾ one ÒÓØØf with type .

The examples that we have seen in this section are amusing to play with, but : they might not convince you that F< is a system of tremendous practical impor- tance! We will come to some more interesting uses of bounded quantification in Chapter 28, but these will require just a little more machinery, which we will de- velop in the intervening chapters. January 15, 2000 20. BOUNDED QUANTIFICATION 167

20.4 Safety

We now consider the metatheory of both kernel and full systems of bounded quan-

k f

F F <:

tification ( <: and ). Much of the development is the same for both systems: we

k f

F F <:

carry it out first for the simpler case of <: and then consider . The type preservation property can actually be proved quite directly for both systems, with minimal technical preliminaries. This is good, since the soundness of the type system is a critical property, while other properties such as may be less important in some contexts. (The soundness theorem belongs in the language definition, while decision procedures are buried in the compiler.) We

k f

F F <:

develop the proof in detail for <: . The argument for is very similar. We begin with a couple of technical facts about the typing and subtyping rela- tions. The proofs go by straightforward induction on derivations.

20.4.1 Lemma [Permutation]:

` Ø : Ì ¡ ¡ ` Ø : Ì

1. If and is a permutation of , then .

` Ë <: Ì ¡ ¡ ` Ë <: Ì ¾ 2. If and is a permutation of , then .

20.4.2 Lemma [Weakening]:

` Ø : Ì Ü ¾= ´ µ ; Ü:Ë ` Ø : Ì

1. If and dom , then .

` Ø : Ì X ¾= ´ µ ; X<:Ë ` Ø : Ì

2. If and dom , then .

` Ë <: Ì Ü ¾= ´ µ ; Ü:Ë ` Ë <: Ì

3. If and dom , then .

` Ë <: Ì X ¾= ´ µ ; X<:Ë ` Ë <: Ì ¾ 4. If and dom , then .

As usual, the proof of type preservation relies on several lemmas relating sub-

stitution with the typing and subtyping relations.

X 7! Ëg Ë

20.4.3 Definition: We write f for the context obtained by substituting for

¾ X in the right-hand sides of all of the bindings in .

20.4.4 Exercise [Quick check]: Show the following properties of subtyping and

typing derivations:

X<:É;¡ ` Ë <: Ì ` È <: É ; X<:È;¡` Ë <: Ì

1. if ; and , then ;

X<:É;¡ ` Ø : Ì ` È <: É ; X<:È;¡` Ø : Ì 2. if ; and , then ;

These properties are often called narrowing because they involve restricting the ¾ range of the variable X.

Next, we have the usual lemma relating substitution and the typing relation.

January 15, 2000 20. BOUNDED QUANTIFICATION 168

Ü:É;¡ ` Ø : Ì ` Õ : É

20.4.5 Lemma [Substitution preserves typing]: If ; and ,

` fÜ 7! ÕgØ : Ì ¾

then ; ¡ .

Ü:É;¡ ` Ø : Ì Proof: Straightforward induction on a derivation of ; , using the

properties proved above. ¾

Since we may substitute types for type variables during reduction, we also need a lemma relating type substitution and typing, as we did in System F. Here, though, we must deal with one new twist: the proof of this lemma (specifically, the T-SUB

case) depends on a new lemma relating substitution and subtyping:

X<:É; ¡ ` Ë <: Ì

20.4.6 Lemma [Type substitution preserves subtyping]: If ;

` È <: É ; fX 7! Èg¡ ` fX 7! ÈgË <: fX 7! ÈgÌ ¾

and , then .

X<:É;¡` Ë <: Ì Proof: By induction on a derivation of ; . The only interesting

cases are the last two:

= Y Y<:Ì ¾ ´ ; X<:É;¡µ´Yµ

Case S-TVAR: Ë

6= X

There are two subcases to consider. If Y , then the result follows immediately

= X Ì = É fX 7! ÈgË = É from S-TVAR. On the other hand, if Y , then we have and ,

and the result follows by S-REFL.

Ë = 8Z<:Í ºË Ì = 8Z<:Í ºÌ

¾ ½ ¾

Case S-ALL: ½

; X<:É;¡;Z<:Í ` Ë <: Ì

½ ¾ ¾

; fX 7! Èg¡; Z<:fX 7! ÈgÍ ` fX 7! ÈgË <: fX 7! ÈgÌ

¾ ¾

By the induction hypothesis, ½ .

; fX 7! Èg¡ `8Z<:fX 7! ÈgÍ ºfX 7! ÈgË <: 8Z<:fX 7! ÈgÍ ºfX 7! ÈgÌ

¾ ½ ¾

By S-ALL, ½ ,

; fX 7! Èg¡ ` fX 7! Èg´8Z<:Í ºË µ <: fX 7! Èg´8Z<:Í ºÌ µ ¾

¾ ½ ¾

that is, ½ , as required.

X<:É; ¡ ` Ø : Ì

20.4.7 Lemma [Type substitution preserves typing]: If ; and

` È <: É ; fX 7! Èg¡ ` fX 7! ÈgØ : fX 7! ÈgÌ ¾

, then .

X<:É; ¡ ` Ø : Ì Proof: By induction on a derivation of ; . We give just the

interesting cases.

Ø = Ø [Ì ] ; X<:É;¡` Ø : 8Z<:Ì ºÌ

¾ ½ ½½ ½¾

Case T-TAPP: ½

Ì = fZ 7! Ì gÌ

¾ ½¾

; fX 7! Èg¡ ` fX 7! ÈgØ : fX 7! Èg´8Z<:Ì ºÌ µ

½½ ½¾

By the induction hypothesis, ½ ,

; fX 7! Èg¡ ` fX 7! ÈgØ : 8Z<:Ì ºfX 7! ÈgÌ ; fX 7! Èg¡ `

½½ ½¾

i.e, ½ .ByT-TAPP,

fX 7! ÈgØ [´fX 7! ÈgÌ ]µ : fZ 7! fX 7! ÈgÌ g´fX 7! ÈgÌ µ ; fX 7! Èg¡ ` fX 7!

¾ ¾ ½¾

½ , i.e.,

Èg´Ø [Ì ]µ : fX 7! Èg´fZ 7! Ì gÌ µ

¾ ¾ ½¾

½ .

X<:É;¡` Ø : Ë ; X<:É;¡` Ë <: Ì

Case T-SUB: ;

fX 7! Èg¡ ` fX 7! ÈgØ : fX 7! ÈgÌ

By the induction hypothesis, ; . By the preserva-

fX 7! Èg¡ ` fX 7! ÈgË <: fX 7! ÈgÌ tion of subtyping under substitution (20.4.6), ; ,

and the result follows by T-SUB. ¾

Next, we establish some simple structural facts about the subtype relation. January 15, 2000 20. BOUNDED QUANTIFICATION 169

20.4.8 Lemma [Inversion of the subtyping relation, from right to left]:

` Ë <: X Ë

1. If , then is a type variable.

` Ë <: Ì !Ì Ë Ë = Ë !Ë

¾ ½ ¾

2. If ½ , then either is a type variable or else with

` Ì <: Ë ` Ë <: Ì

½ ¾ ¾

½ and .

` Ë <: 8X<:Í ºÌ Ë Ë = 8X<:Í ºË

¾ ½ ¾

3. If ½ , then either is a type variable or else

; X<:Í ` Ë <: Ì ¾

¾ ¾ with ½ .

Proof: Part (1) follows by an easy induction on subtyping derivations. The only interesting case is the rule S-TRANS, which proceeds by two uses of the induction hypothesis, first on the right premise and then on the left. The arguments for the

other parts are similar (part (1) is used in the transitivity cases). ¾

20.4.9 Exercise: Show the following “left to right inversion” properties:

` Ë !Ë <: Ì Ì = ÌÓÔ Ì = Ì !Ì ` Ì <: Ë

¾ ½ ¾ ½ ½

1. If ½ , then either or else with

` Ë <: Ì ¾

and ¾ .

`8X<:ÍºË <: Ì Ì = ÌÓÔ Ì = 8X<:ÍºÌ ; X<:Í ` ¾

2. If ¾ , then either or else with

Ë <: Ì ¾

¾ .

` X <: Ì Ì = ÌÓÔ Ì = X ` Ë <: Ì X<:Ë ¾

3. If , then either or or , where .

` ÌÓÔ <: Ì Ì = ÌÓÔ ¾ 4. If , then .

We use Lemma 20.4.8 for one straightforward structural property of the typing relation that will be needed in the critical cases of the type preservation proof.

20.4.10 Lemma:

` Ü:Ë º× : Ì ` Ì <: Í !Í ` Í <: Ë

¾ ½ ¾ ½ ½

1. If ½ and , then and there is some

Ë ; Ü:Ë ` × : Ë ` Ë <: Í

½ ¾ ¾ ¾ ¾

¾ such that and .

` X<:Ë º× : Ì ` Ì <: 8X<:Í ºÍ Í = Ë

¾ ½ ¾ ½ ½

2. If ½ and , then and there is some

Ë ; X<:Ë ` × : Ë ; X<:Ë ` Ë <: Í ¾

½ ¾ ¾ ½ ¾ ¾ ¾ such that and .

Proof: Straightforward induction on typing derivations, using Lemma 20.4.8 for

the induction case (rule T-SUB). ¾

With all these facts in-hand, the actual proof of type preservation is straightfor-

ward.

¼ ¼

` Ø : Ì ` Ø ! Ø ` Ø : Ì ¾

20.4.11 Theorem [Preservation]: If and , then .

` Ø : Ì Proof: By induction on a derivation of . All of the cases are straightfor- ward, using the facts established in the above lemmas.

January 15, 2000 20. BOUNDED QUANTIFICATION 170

= Ü

Case T-VAR: Ø

¼

` Ø ! Ø This case cannot actually arise, since we assumed and there are no

evaluation rules for variables.

Ø = Ü:Ì ºØ ¾ Case T-ABS: ½

Ditto.

Ø = Ø Ø ` Ø : Ì !Ì

¾ ½ ½½ ½¾

Case T-APP: ½

Ì = Ì ` Ø : Ì

½¾ ¾ ½½

By the definition of the evaluation relation, there are three subcases to consider:

¼ ¼ ¼

` Ø ! Ø Ø = Ø Ø ¾

Subcase: ½ ½ ½

Then the result follows from the induction hypothesis and T-APP.

¼ ¼ ¼

Ø ` Ø ! Ø Ø = Ø Ø

¾ ½

Subcase: ½ is a value

¾ ¾

Similar.

¼

Ø = Ü:Í ºÙ Ø = fÜ 7! Ø gÙ

½½ ½¾ ¾ ½¾

Subcase: ½

; Ü:Í ` Ù : Í ` Ì <: Í ` Í <: Ì

½¾ ½¾ ½½ ½½ ½¾ ½¾

By Lemma 20.4.10, ½½ with and .

` fÜ 7!

By the preservation of typing under substitution (Lemma 20.4.5),

Ø gÙ : Í ` fÜ 7! Ø gÙ : Ì

½¾ ½¾ ¾ ½¾ ½¾

¾ , from which follows by T-SUB.

= X<:꼯 Case T-TABS: Ø

Can’t happen.

Ø = Ø [Ì ] ` Ø : 8X<:Ì ºÌ

¾ ½½ ½¾

Case T-TAPP: ½

Ì = fX 7! Ì gÌ ` Ì <: Ì

¾ ½¾ ¾ ½½

By the definition of the evaluation relation, there are two subcases to consider:

¼ ¼ ¼

Ø ! Ø Ø = Ø [Ì ] ½

Subcase: ¾ ½ ½

The result follows from the induction hypothesis and T-TAPP.

¼

Ø = X<:Í ºÙ Ø = fX 7! Ì gÙ

½½ ½¾ ¾ ½¾

Subcase: ½

Í = Ì ; X<:Í ` Ù : Í ; X<:Í `

½½ ½½ ½¾ ½¾ ½½

By Lemma 20.4.10, ½½ and with

Í <: Ì ` fX 7! ½¾

½¾ . By the preservation of typing under substitution (20.4.5),

Ì gÙ : fX 7! Ì gÍ ` fX 7! Ì gÙ : fX 7! Ì gÌ

½¾ ¾ ½¾ ¾ ½¾ ¾ ½¾ ¾ , from which follows by

Lemma 20.4.6 and T-SUB.

` Ø : Ë ` Ë <: Ì

Case T-SUB:

¼

` Ø : Ë ¾ By the induction hypothesis, ; the result follows by T-SUB.

f

F ¾ 20.4.12 Exercise: Show how to extend the argument in this section to <: . January 15, 2000 20. BOUNDED QUANTIFICATION 171

20.5 Bounded Existential Types

This final section remains to be written.

k

F 9

Bounded existential quantification <: +

New syntactic forms

Ì ::= ... (types...)

9X <:Ì ¸Ì}

ß existential type

` Ë <: Ì

New subtyping rules ( )

; X<:Í ` Ë <: Ì ¾

¾ (S-SOME)

` ß9X<:Í¸Ë } <: ß9X<:Í¸Ì }

¾ ¾

` Ø : Ì

New typing rules ( )

` Ø : fX 7! ÍgÌ ` Í <: Ì

¾ ¾ ½

(T-PACK)

` ß9X=Í¸Ø } a× ß9X <:Ì ¸Ì } : ß9X <:Ì ¸Ì }

¾ ½ ¾ ½ ¾

` Ø : 9X ºÌ ; X ; Ü:Ì ` Ø : Ì

<:Ì <:Ì

½ ½¾ ½¾ ¾ ¾

½½ ½½

(T-UNPACK)

` ÐeØ ßX¸Ü}=Ø iÒ Ø : Ì

½ ¾ ¾

20.5.1 Exercise: Show how the subtyping rule S-SOME can be obtained from the subtyping rules for universals by extending the encoding of existential types in

terms of universal types described in Section 19.3. ¾

20.6 Historical Notes and Further Reading

The idea of bounded quantification was introduced by Cardelli and Wegner [CW85]

k F

in the language Fun. (Their “Kernel Fun” calculus corresponds to our <: .) Based on informal ideas by Cardelli and formalized using techniques developed by Mitchell [Mit84b], Fun integrated Girard-Reynolds polymorphism [Gir72, Rey74] with Cardelli’s first-order calculus of subtyping [?, Car84]. The original Fun was simplified and slightly generalized by Bruce and Longo [BL90], and again by Curien and Ghelli [CG92],

f F yielding the calculus we call <: . The most comprehensive single paper on bounded quantification is the survey by Cardelli, Martini, Mitchell, and Scedrov [CMMS94]. Fun and its relatives have been studied extensively by programming language theorists and designers. Cardelli and Wegner’s survey paper gives the first pro- gramming examples using bounded quantification; more are developed in Cardelli’s

study of power kinds [Car88]. Curien and Ghelli [CG92, Ghe90] address a number : of syntactic properties of F< . Semantic aspects of closely related systems have been studied by Bruce and Longo [BL90], Martini [Mar88], Breazu-Tannen, Coquand, January 15, 2000 20. BOUNDED QUANTIFICATION 172

Gunter, and Scedrov [BCGS91], Cardone [Car89], Cardelli and Longo [CL91], Cardelli,

Martini, Mitchell, and Scedrov [?], Curien and Ghelli [CG92, CG91], and Bruce and : Mitchell [BM92]. F < has been extended to include record types and richer notions of inheritance by Cardelli and Mitchell [CM91], Bruce [Bru91], Cardelli [Car92], and Canning, Cook, Hill, Olthoff, and Mitchell [CCH· 89]. Bounded quantification also plays a key role in Cardelli’s programming language Quest [Car91, CL91] and

in the Abel language developed at HP Labs [CCHO89, CCH · 89, CHO88, CHC90]. : The undecidability of full F< was shown by Pierce [Pie94] and further analyzed by Ghelli [Ghe95]. The effect of bounded quantification on Church encodings of algebraic datatypes (cf. Section 20.3) was considered by Ghelli thesis [Ghe90] and Cardelli, Martini,

Mitchell, and Scedrov [CMMS94]. : An extension of F< with intersection types was studied by Pierce [Pie91a, Pie97] and applied to the modeling of object-oriented languages with multiple inheri- tance by Compagnoni and Pierce [CP96]. Chapter 21

Implementing Bounded Quantification

Next we consider the problem of building a typechecking algorithm for a language with bounded quantifiers. The algorithm that we construct will be parametric in an algorithm for the subtype relation, which we consider in the following section.

21.1 Promotion 

In the typechecking algorithm for <: in Section 13.2, the key idea was that we can calculate a minimal type for each term from the minimal types of its subterms. We

k F

will use the same basic idea to typecheck <: , but we need to take into account one slight complication arising from the presence of type variables in the system.

Consider the term

f = X<:ÆaØ! Æaغ Ý:Xº Ý 5;

Á

f : 8X<:ÆaØ! Æaغ X ! ÆaØ

This term is clearly well typed, since the type of the variable Ý in the application

5µ X ÆaØ!ÆaØ ´Ý is , which can be promoted to by T-SUB. But the minimal type

of Ý is not an arrow type. In order to find the minimal type of the application, we

need to find the minimal arrow type that Ý possesses—i.e., the minimal arrow type

that is a supertype of X. Not too surprisingly, the correct way to find this type is to

promote the minimal type of Ý until it is something other than a type variable.

` Ë ¶ Ì Ì Ë Formally, write to mean “ is the least nonvariable supertype of ,” defined by repeated promotion of variables as follows:

173 January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 174

Exposure

¼

Á

` Ì ¶ Ì

Exposure ( )

¼

Á

X<:Ì ¾ ` Ì ¶ Ì

(XA-PROMOTE)

¼

Á

` X ¶ Ì

Ì is not a type variable

(XA-OTHER)

Á

` Ì ¶ Ì

It is easy to check that these rules define a total function. Moreover, the re- sult of promotion is always the least supertype that has some shape other than a

variable.

` Ë ¶ Ì

21.1.1 Lemma: Suppose .

` Ë <: Ì

1. .

` Ë <: Í Í ` Ì <: Í ¾ 2. If and is not a variable, then .

Proof: Part (1) is easy. Part (2) goes by straightforward induction on a derivation

` Ë <: Í ¾ of .

21.2 Minimal Typing

The algorithm for calculating minimal types is built along the same basic lines as  the one for <: , with one additional twist: the minimal type of a term may always be a type variable, and such a type will need to be promoted to its smallest non- variable supertype (its smallest concrete supertype, we might say) in order to be used on the left of an application or type application.

Algorithmic typing

Á

` Ø : Ì

Algorithmic typing ( )

Ü:Ì ¾

(TA-VAR)

Á

` Ü : Ì

Á

; Ü:Ì ` Ø : Ì

½ ¾ ¾

(TA-ABS)

Á

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

Á Á Á Á

` Ø : Ì ` Ì ¶ ´Ì !Ì µ ` Ø : Ì ` Ì <: Ì

½ ½ ½ ½½ ½¾ ¾ ¾ ¾ ½½

Á

` Ø Ø : Ì

½ ¾ ½¾ (TA-APP)

January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 175

Á

; X ` Ø : Ì

<:Ì

¾ ¾

½ (TA-TABS)

Á

` X <:Ì ºØ : 8X <:Ì ºÌ

½ ¾ ½ ¾

Á Á Á

` Ø : Ì ` Ì ¶ 8X<:Ì ºÌ ` Ì <: Ì

½ ½ ½½ ½¾ ¾ ½½

½ (TA-TAPP)

Á

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾

The proofs of soundness and completeness of this algorithm with respect to the original typing rules are fairly routine.

21.2.1 Theorem [Minimal typing]:

Á

` Ø : Ì ` Ø : Ì

1. If , then .

Á

` Ø : Ì ` Ø : Å ` Å <: Ì ¾ 2. If , then where .

Proof: Part (1) proceeds by a straightforward induction on algorithmic deriva-

` Ø : Ì tions. Part (2) is more interesting; it goes by induction on a derivation of .

(The most important cases are those for the rules T-APP and T-TAPP.)

= Ü Ü:Ì ¾

Case T-VAR: Ø

Á

` Ü : Ì ` Ì <: Ì

By TA-VAR, . By S-REFL, .

Ø = Ü:Ì ºØ ; Ü:Ì ` Ø : Ì Ì = Ì !Ì

¾ ½ ¾ ¾ ½ ¾

Case T-ABS: ½

Á

; Ü:Ì ` Ø : Å Å ; Ü:Ì ` Å <: Ì

¾ ¾ ¾ ½ ¾ ¾

By the induction hypothesis, ½ for some with ,

` Å <: Ì ¾

i.e. (since subtyping does not depend on term variable bindings), ¾ .By

` Ø : Ì !Å ` Ì !Å <:

¾ ½ ¾

TA-ABS, ½ . Finally, by S-REFL and S-ARROW, we have

Ì !Ì ¾

½ .

Ø = Ø Ø ` Ø : Ì !Ì

¾ ½ ½½ ½¾

Case T-APP: ½

Ì = Ì ` Ø : Ì

½¾ ¾ ½½

Á Á

` Ø : Å ` Ø : Å ` Å <:

½ ¾ ¾ ½

By the induction hypothesis, we have ½ and , with

Ì !Ì ` Å <: Ì Æ Å

½¾ ¾ ½½ ½ ½

½½ and . Let be the least nonvariable supertype of —i.e.,

` Å ¶ Æ ` Æ <: Ì !Ì

½ ½ ½½ ½¾

suppose ½ . By the promotion lemma (21.1.1), . But Æ

we know that ½ is not a variable, so the inversion lemma for the subtype relation

Æ = Æ !Æ ` Ì <: Æ ` Æ <: Ì

½½ ½¾ ½½ ½½ ½¾ ½¾

(20.4.8) tells us that ½ , with and .By

Á

` Å <: Æ ` Ø Ø : Æ

½½ ½ ¾ ½¾ transitivity, ¾ , so rule TA-APP applies and gives us ,

which satisfies the requirements.

Ø = X<:Ì ºØ ; X<:Ì ` Ø : Ì Ì = 8X<:Ì ºÌ

¾ ½ ¾ ¾ ½ ¾

Case T-TABS: ½

Á

; X<:Ì ` Ø : Å Å ; X<:Ì ` Å <:

¾ ¾ ¾ ½ ¾

By the induction hypothesis, ½ for some with

Á

Ì ` Ø : 8X<:Ì ºÅ

½ ¾

¾ . By TA-TABS, . Finally, by S-REFL and S-ALL, we have

`8X<:Ì ºÅ <: 8X<:Ì ºÌ

¾ ½ ¾ ½ .

January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 176

Ø = Ø [Ì ] ` Ø : 8X<:Ì ºÌ

¾ ½ ½½ ½¾

Case T-TAPP: ½

Ì = fX 7! Ì gÌ ` Ì <: Ì

¾ ½¾ ¾ ½½

Á

` Ø : Å ` Å <: 8X<:Ì ºÌ

½ ½ ½½ ½¾

By the induction hypothesis, we have ½ , with .

Æ Å ` Å ¶ Æ

½ ½ ½

Let ½ be the least nonvariable supertype of —i.e., suppose .By

` Æ <: 8X<:Ì ºÌ Æ

½½ ½¾ ½ the promotion lemma (21.1.1), ½ . But we know that is

not a variable, so the inversion lemma for the subtype relation (20.4.8) tells us that

Æ = 8X<:Æ ºÆ Æ = Ì ; X<:Ì ` Æ <: Ì

½½ ½¾ ½½ ½½ ½½ ½¾ ½¾

½ , with and . Rule TA-TAPP

Á

` Ø [Ì ] : fX 7! Ì gÆ

¾ ¾ ½¾

gives us ½ , and the preservation of subtyping under

` fX 7! Ì gÆ <: fX 7! Ì gÌ = Ì

½¾ ¾ ½¾

substitution (20.4.6) yields ¾ .

` Ø : Ë ` Ë <: Ì

Case T-SUB:

Á

` Ø : Å ` Å <: Ë ` Å <: Ì By the induction hypothesis, with . By S-TRANS, ,

from which T-SUB yields the desired result. ¾

k F

21.2.2 Corollary [Decidability of typing]: The <: typing relation is decidable (if

we are given a decision procedure for the subtyping relation). ¾

Ø Ì ` Ø : Ì

Proof: Given and , we can check whether there is some such that by

Á

` Ø : Ì

using the algorithmic typing rules to generate a proof of . If we succeed, Ì then this Ì is also a type for in the original typing relation (by part (1) of 21.2.1). If

not, then part (2) of 21.2.1 implies that Ø has no type in the original typing relation. Finally, note that the algorithmic typing rules constitute a terminating algo-

rithm, since they are syntax-directed and always reduce the size of Ø when read

from bottom to top. ¾

21.2.3 Exercise: Show how to add primitive booleans and conditionals to the min-

k

F ¾

imal typing algorithm for <: . (Solution on page 261.)

k F

21.3 Subtyping in <:

As we saw in the simply typed lambda-calculus with subtyping, the subtyping rules in their present form do not constitute an algorithm for deciding the subtyp- ing relation. We cannot use them “from bottom to top,” for two reasons: 1. There are some overlaps between the conclusions of different rules (specifi-

cally, between S-REFL and nearly all the other rules). That is, looking at the

` Ë <: Ì form of a derivable subtyping statement , we cannot decide which of the rules must have been used last in deriving it.

2. More seriously, one rule (S-TRANS) contains a metavariable in the premises that does not appear in the conclusion. To apply this rule from botom to top, we’d need to guess what type to replace this metavariable with. January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 177

The overlap between S-REFL and the other rules is easily dealt with, using ex- actly the same technique as we used in Chapter 13: we remove the full reflexivity

rule and replace it by a restricted reflexivity rule that applies only to type variables.

` X <: X

Next we must deal with S-TRANS. Unfortunately, unlike the simple subtyping relation studied in Chapter 13, the transitivity rule here interacts in an important way with another rule—namely S-TVAR, which allows assumptions about type

variables to be used in deriving subtyping statements. For example, if

= Ï<:ÌÓÔ; X<:Ï; Y<:X; Z<:Y

then the statement

` Z <: Ï is provable using all the subtyping rules, but cannot be proved if S-TRANS is re- moved. That is, an instance of S-TRANS whose left-hand subderivation is an in- stance of the axiom S-TVAR,asin .

. µ

´ S-TVAR

` Z <: Y ` Y <: Ï µ

´ S-TRANS

` Z <: Ï cannot, in general, be eliminated. Fortunately, it turns out that derivations of this form are the only essential uses of transitivity in subtyping. This observation can be made precise by introducing

a new subtyping rule

X<:Í ¾ ` Í <: Ì

` X <: Ì that captures exactly this pattern of variable lookup followed by transitivity, and showing (as we will do below) that replacing the transitivity and variable rules by this one does not change the set of derivable subtyping statements. These intuitions are summarized in the following definition. The algorithmic

k F

subtype relation of <: is the least relation closed under the following rules:

Algorithmic subtyping

Á

` Ë <: Ì

Algorithmic subtyping ( )

Á

` Ë <: ÌÓÔ

(SA-TOP)

Á

` X <: X

(SA-REFL-TVAR)

Á

X<:Í ¾ ` Í <: Ì

(SA-TRANS-TVAR)

Á

` X <: Ì

January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 178

Á Á

` Ì <: Ë ` Ë <: Ì

½ ¾ ¾

½ (SA-ARROW)

Á

` Ë !Ë <: Ì !Ì

½ ¾ ½ ¾

Á

; X<:Í ` Ë <: Ì

¾ ¾

½ (SA-ALL)

Á

` 8X<:Í ºË <: 8X<:Í ºÌ

½ ¾ ½ ¾

Á `

21.3.1 Lemma [Reflexivity of the algorithmic subtype relation]: The statement

Ì <: Ì Ì ¾

is provable for all and . ¾

Proof: Easy induction on Ì.

Á

` Ë <: É

21.3.2 Lemma [Transitivity of the algorithmic subtype relation]: If

Á Á

` É <: Ì ` Ë <: Ì ¾ and , then .

Proof: By induction on the sum of the sizes of the two derivations. Given two derivations of some total size, we proceed by considering the final rules in each.

First, if the right-hand derivation is an instance of SA-TOP, then we are done,

` Ë <: ÌÓÔ

since by SA-TOP. Moreover, if the left-hand derivation is an instance

= ÌÓÔ of SA-TOP, then É and by looking at the algorithmic rules we see that the right-hand derivation must also be an instance of SA-TOP. If either derivation is an instance of SA-REFL-TVAR, then we are again done since the other derivation is the desired result.

Next, if the left-hand derivation ends with an instance of SA-TRANS-TVAR,

= X X<:Í ¾ ` Í <: É

then Ë with and we have a subderivation with conclusion .

Á Á

` Í <: Ì ` X <: By the induction hypothesis, , and, by SA-TRANS-TVAR again,

Ì, as required.

If the left-hand derivation ends with an instance of SA-ARROW, then we have

Á Á

Ë = Ë !Ë É = É !É ` É <: Ë ` Ë <: É

¾ ½ ¾ ½ ½ ¾ ¾ ½ and , with subderivations and . But, since we have already considered the case where the right-hand derivation is

SA-TOP, the only remaining possibility is that the right-hand derivation also ends

Ì = Ì !Ì ¾

with SA-ARROW; we therefore have ½ , and two more subderivations

Á Á

` Ì <: É ` É <: Ì

½ ¾ ¾

½ and . We now apply the induction hypothesis twice,

Á Á Á

` Ì <: Ë ` Ë <: Ì ` Ë !Ë <:

½ ¾ ¾ ½ ¾

obtaining ½ and . Finally, SA-ARROW yields

Ì !Ì ¾ ½ , as required. The case where the left-hand derivation ends with an instance of SA-ALL is

similar. ¾

21.3.3 Theorem [Soundness and completeness of algorithmic subtyping]:

Á

` Ë <: Ì ` Ë <: Ì

1. If then .

Á

` Ë <: Ì ` Ë <: Ì ¾ 2. If then . January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 179

Proof: Both directions proceed by induction on derivations. Soundness is routine. Completeness is also straightforward, since we have already done the hard work (for the reflexivity and transitivity rules of the original subtype relation) in Lem-

mas 21.3.1 and 21.3.2. ¾

Finally, we should check that the subtyping rules define an algorithm that is total—i.e., that always terminates no matter what input it is given. We do this by assigning a weight to each subtyping statement, and checking that the algorithmic

rules all have conclusions with greater weight than their premises.

´Ìµ

21.3.4 Definition: The weight of a type Ì in a context , written weight ,isde-

fined as follows:

´Xµ = ´Íµ·½ = ; X<:Í; ¾

weight weight if ½

½

ÌÓÔµ = ½

weight ´

´Ì !Ì µ = ´Ì µ· ´Ì µ· ½

¾ ½ ¾

weight ½ weight weight

´8X<:Ì ºÌµ = ´Ì µ·½ ¾

weight ½ weight

; X<:Ì

½

` Ë <: Ì Ë

The weight of a subtyping statement “ ” is the maximum weight of and

¾ Ì in .

21.3.5 Theorem: The weight of the conclusion in an instance of any of the algorith-

mic subtyping rules is strictly greater than the weight of any of the premises. ¾

Proof: Straightforward inspection of the rules. ¾

f F

21.4 Subtyping in <:

f F The only difference in the full system <: is that the quantifier subtyping rule S-ALL

is replaced by the more expressive variant:

` Ì <: Ë ; X<:Ì ` Ë <: Ì

½ ½ ½ ¾ ¾

(S-ALL)

`8X<:Ë ºË <: 8X<:Ì ºÌ

½ ¾ ½ ¾

f F The algorithmic subtype relation of <: consists of exactly the same set of rules k F LL as the algorithm for <: , except that SA-A is refined to reflect the new version of

S-ALL:

Á

` Ì <: Ë ; X<:Ì ` Ë <: Ì

½ ½ ½ ¾ ¾

(SA-ALL)

Á

` 8X<:Ë ºË <: 8X<:Ì ºÌ

½ ¾ ½ ¾

k F

As with <: , the soundness and completeness of this algorithmic relation with respect to the original subtype relation can be shown easily, once we have estab- lished that the algorithmic relation is reflexive and transitive. For reflexivity, the argument is exactly the same as before. For transitivity, on the other hand, the issues are more subtle. January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 180

21.4.1 Lemma [Transitivity and narrowing]:

Á Á Á

` Ë <: É ` É <: Ì ` Ë <: Ì

1. If and , then .

Á Á Á

X<:É;¡ ` Å <: Æ ` È <: É ; X<:È;¡ ` Ë <: Ì ¾ 2. If ; and then .

Proof: The two parts are proved simultaneously, by induction on the size of É.At each stage of the induction, the argument for part (2) assumes that part (1) has been

established already for the É in question; part (1), on the other hand, uses part (2)

only for strictly smaller És.

1. Most of the argument is identical to the proof of 21.3.2. The only differ- ence lies in the case where both of the given derivations end in instances

of SA-ALL. In this case, we have

Ë = 8X<:Ë ºË

½ ¾

É = 8X<:É ºÉ

½ ¾

Ì = 8X<:Ì ºÌ

½ ¾

` É <: Ë

½ ½

Á

; X<:É ` Ë <: É ` Ì <: É

½ ¾ ¾ ½ ½

Á

; X<:Ì ` É <: Ë

½ ¾ ¾

as subderivations. By part (1) of the induction hypothesis, we can immedi-

Á

` Ì <: Ë ½ ately combine the three subderivations for the bounds to obtain ½ . For the bodies, we need to work a little harder, since the two contexts do

not quite agree. We first use part (2) of the induction hypothesis to “nar-

Á

X ; X<:É ` Ë <: É

¾ ¾

row” the bound of in the derivation of ½ , obtaining

Á

; X<:Ì ` Ë <: É

¾ ¾

½ . Now part (1) of the induction hypothesis applies, yield-

Á Á

; X<:Ì ` Ë <: Ì ` 8X<:Ë ºË <: 8X<:Ì ºÌ

¾ ¾ ½ ¾ ½ ¾ ing ½ . Finally, by SA-ALL, , as required.

2. Given É of a certain size, we use an inner induction on the size of a derivation

Á

X<:É; ¡ ` Ë <: Ì of ; , with a case analysis on the last rule used in this

derivation.

Á

= X ; X<:É;¡ `

The only interesting case is SA-TRANS-TVAR, where Ë and

Á

É <: Ì X<:È;¡`

as a subderivation. By the inner induction hypothesis, ;

Á

; X<:È;¡` X <: Ì ¾ <: Ì É . Rule SA-TRANS-TVAR now yields , as required.

k F

21.4.2 Exercise: Show that <: has joins and bounded meets. (Solution on page 261.) ¾

21.4.3 Exercise: Consider the types (due to Ghelli [Ghe90, p. 92])

Ë = 8X<:Y!ZºY!Z January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 181

and

¼ ¼ ¼ ¼

Ì = 8X<:Y !Z ºY !Z

¼ ¼

= Y<:ÌÓÔ; Z<:ÌÓÔ; Y <:Y; Z <:Z and the context .

f

F Ë Ì 1. In <: , how many types are subtypes of both and under .

f

F Ë Ì 2. Show that, in <: , the types and have no meet under .

f

F 3. Exhibit a pair of types that has no join (under )in <: .

(Solution on page 265.) ¾ : 21.5 Undecidability of Subtyping in Full F <

k F

Unfortunately, the proof of termination of the <: subtyping algorithm in Section ??

f F does not work for <: .

21.5.1 Exercise [Quick check]: Why not? ¾

In fact, not only does this particular proof technique not work—the subtyping algorithm actually does not terminate on some inputs. Here is an example, due to Ghelli [Ghe95], that makes the algorithm diverge. First define the following abbreviation:

def

:Ë = 8X<:˺X:

` :Ë <: :Ì ` Ì <: Ë ¾ 21.5.2 Fact: iff .

Proof: Exercise. ¾

Now, define a type Ì as follows:

Ì = 8X<:ÌÓÔº :´8Y<:Xº:Yµ:

If we use the algorithmic subtyping rules bottom-to-top to attempt to construct a

subtyping derivation for the statement

X <:Ì ` X <: ´8X <:X º:X µ

¼ ¼ ½ ¼ ½

we end up in an infinite regress of larger and larger “subgoals”:

X <:Ì ` X <: ´8X <:X º:X µ

¼ ¼ ½ ¼ ½

X <:Ì ` 8X <:ÌÓÔº :´8X <:X º:X µ <: ´8X <:X º:X µ

¼ ½ ¾ ½ ¾ ½ ¼ ½

X <:Ì; X <:X ` :´8X <:X º:X µ <: :X

¼ ½ ¼ ¾ ½ ¾ ½

X <:Ì; X <:X ` X <: ´8X <:X º:X µ

¼ ½ ¼ ½ ¾ ½ ¾

X <:Ì; X <:X ` X <: ´8X <:X º:X µ

¼ ½ ¼ ¼ ¾ ½ ¾ etc. January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 182

The «-conversion steps necessary to maintain the well-formedness of the context when new variables are added are performed tacitly here, choosing new names

so as to clarify the pattern of regress. The crucial trick is the “re-bounding” that X

occurs, for instance, between the second and third lines, where the bound of ½

ÌÓÔ X

on the left-hand side is changed from in line 2 to ¼ in line 3. Since the whole X left-hand side in line 2 is itself the upper-bound of ¼ , the re-bounding creates a cyclic pattern where longer and longer chains of variables in the context must be

traversed on each loop. (The reader is cautioned not to look for semantic intuitions Ì behind this example; in particular, : is a negation only in the sense that it allows the left- and right-hand sides of subtyping judgements to be swapped.) Worse yet, not only does this particular algorithm fail to terminate on some in- puts, it can be shown [Pie94] that there is no algorithm that is sound and complete

f F for the original <: subtyping relation and that terminates on all inputs. The full proof of this fact is beyond the scope of this book (the argument re- quires no particularly deep mathematics, but takes several pages to develop). How- ever, to give a little of its flavor, let’s look at one more example.

21.5.3 Definition: The positive and negative occurences in a type Ì are defined as

follows:

Ì Ì

¯ itself is a positive occurence in .

¯ Ì !Ì Ì

¾ ½

If ½ is a positive (respectively, negative) occurrence, then is a nega- Ì

tive (resp. positive) occurrence and ¾ is a positive (negative) occurrence.

¯ 8X<:Ì ºÌ Ì

¾ ½

If ½ is a positive (respectively, negative) occurrence, then is a neg- Ì

ative (resp. positive) occurrence and ¾ is a positive (negative) occurrence.

` Ë <: Ì

The positive and negative occurences in a subtyping statement are

defined as follows: the type Ë and the bounds of type variables in are negative ¾ occurrences. The type Ì is a positive occurrence.

The words “positive” and “negative” come from logic. According to the well-

known “Curry-Howard isomorphism” [How80, CF58] between propositions and

!Ì Ë µ Ì

types, the type Ë corresponds to the logical proposition , which, by the

Ë _ Ì Ë definition of logical implication, is equivalent to : . The subproposition here is obviously in a “negative” position—that is, inside of an odd number of negations—if and only if the whole implication appears inside an even number of

negations.

Ë Ì X<:Í ` Ë <: Ì

21.5.4 Fact: If X occurs only positively in and negatively in , then

fX 7! ÍgË <: fX 7! ÍgÌ ¾ iff ` .

Proof: Exercise. ¾ January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 183

Now, let Ì be the following (pretty horrible) type

Ì = 8X <:ÌÓÔº8X <:ÌÓÔº8X <:ÌÓÔº

¼ ½ ¾

:´8Y <:X º8Y <:X º8Y <:X º:X µ

¼ ¼ ½ ½ ¾ ¾ ¼

and consider the subtyping statement

` Ì

<: 8X <:̺8X <:Ⱥ8X <:ɺ

¼ ½ ¾

:´8Y <:ÌÓÔº8Y <:ÌÓÔº8Y <:ÌÓÔº

¼ ½ ¾

:´8Z <:Y º8Z <:Y º8Z <:Y º ͵µ:

¼ ¼ ½ ¾ ¾ ½

We can think of this statement as a description of the state of a simple computer:

¯ X X ¾

The variables ½ and are the “registers” of this machine. Their current É contents are the types È and .

¯ The “instruction ” of the machine is the last line of the statement: the

Y Y ½

first instruction is encoded in the bounds ( ¾ and —note their order!) of

Z Z Í ¾ the variables ½ and , and the type is the remaining instructions in the

program.

¯ Ì X Y ¼ The type , the nested negations, and the bound variables ¼ and here play much the same role as their counterparts in the simpler example above: they allow us to “turn the crank” and get back to a subgoal of the same shape as the original goal. One turn of the crank will correspond to one cycle of our machine.

In this example, the instruction at the front of the instruction stream encodes the ¾

command “switch the contents of registers ½ and .” To see this, we use the two É facts stated above to calculate as follows. (The values È and in the two registers

are highlighted, to make them easier to track through the derivation.)

` Ì

<: 8X <:̺8X <: Ⱥ8X <: ɺ

¼ ½ ¾

:´8Y <:ÌÓÔº8Y <:ÌÓÔº8Y <:ÌÓÔº

¼ ½ ¾

:´8Z <:Y º8Z <:Y º8Z <:Y º ͵µ

¼ ¼ ½ ¾ ¾ ½

` :´8Y <:̺8Y <: Ⱥ8Y <: ɺ:̵

½ ¾

iff ¼

<: :´8Y <:ÌÓÔº8Y <:ÌÓÔº8Y <:ÌÓÔº

½ ¾

¼ by Fact 21.5.4

:´8Z <:Y º8Z <:Y º8Z <:Y º ͵µ

¼ ¼ ½ ¾ ¾ ½

` ´8Y <:ÌÓÔº8Y <:ÌÓÔº8Y <:ÌÓÔº

½ ¾

iff ¼

:´8Z <:Y º8Z <:Y º8Z <:Y º ͵µ

¼ ¼ ½ ¾ ¾ ½

Ⱥ8Y <: ɺ:̵ <: ´8Y <:̺8Y <:

¾ ½

¼ by Fact 21.5.2

` :´8Z <:̺8Z <: ɺ8Z <: Ⱥ ͵µ

½ ¾

iff ¼

: :Ì

< by Fact 21.5.4 Ì

iff `

<: ´8Z <:̺8Z <: ɺ8Z <: Ⱥ ͵µ

½ ¾ ¼ by Fact 21.5.2

January 15, 2000 21. IMPLEMENTING BOUNDED QUANTIFICATION 184 É Note that, at the end of the derivation, not only have the values È and switched places, but the instruction that caused this to happen has been used up in the pro-

cess, leaving Í at the front of the instruction stream to be “executed” next. By

choosing a value of Í that begins in the same way as the instruction we just exe-

cuted

Í = :´8Y <:ÌÓÔº8Y <:ÌÓÔº8Y <:ÌÓÔº

¼ ½ ¾

¼

:´8Z <:Y º8Z <:Y º8Z <:Y º Í µµ

¼ ¼ ½ ¾ ¾ ½

we can perform another swap and return the registers to their original state before

¼ Í continuing with Í . More interestingly, we can choose other values for that cause

different sorts of behavior. For example, if

Í = :´8Y <:ÌÓÔº8Y <:ÌÓÔº8Y <:ÌÓÔº

¼ ½ ¾

:´8Z <:Y º8Z <:Y º8Z <:Y º Y µµ

¼ ¼ ½ ½ ¾ ¾ ½ É

then, on the next cycle of the machine, the current value of register ½ ( ) will appear ½ in the position of Í—in effect, performing an “indirect branch” through register

to the stream of instructions É. Conditional constructs and arithmetic (successor, predecessor, and zero-test) can be encoded using a generalization of this trick. Putting all of this together, we arrive at a proof of undecidability, via a reduc- tion from two-counter machines—a simple variant on ordinary turing machines, consisting of a finite control and two counters, each holding a natural number (cf. [HU79], for example)—to subtyping statements.

21.5.5 Theorem [Undecidability]: For each two-counter machine Å, there exists a

f

˴ŵ ˴ŵ F Šsubtyping statement such that is derivable in <: iff the execution of

halts. ¾

Thus, if we could decide whether any subtype statement is provable, then we could also decide whether any given two-counter machine will eventually halt.

21.5.6 Exercise [Challenging]:

f

F ÌÓÔ X<:Ì X 1. Define a variant of <: with no type but with both and bindings. 2. Show that the subtype relation for this system is decidable. 3. Does this restriction offer a satisfactory solution to the basic problem? In par- ticular, does it work for languages with additional features such as numbers, records, variants, etc.?

(Hint on page 265.) ¾ Chapter 22

Denotational Semantics By Martin Hofmann and Benjamin Pierce

Some notation is out of date in this chapter. Denotational semantics is a compositional assigment of mathematical objects to program phrases (terms, types, and typing and subtyping statements). Composi- tionality means that the meaning of a phrase is defined in terms of its outermost constructor and the meanings of its immediate subphrases. The foremost and easiest application of semantics is demonstrating the sound- ness and consistency of equational theories—in particular, the one generated by the reduction rules. (To show that the equational theory is sound, we show that terms equated by the theory have equal interpretations; to show that it is consistent— i.e., that not all terms are equated by the equational theory—it suffices to exhibit two terms with different interpretations.) Semantic models can also suggest exten- sions to the syntax, in particular program logics. If a semantics is “computationally adequate” (we’ll come back to this term later

on), it can also be used to reason about observational equivalence of programs.

= ßÜ=¼¸Ý=¼}

For example, it is intuitively the case that the two records Ô and

= ßÜ=¼¸Ý=½} ß Ü:ÆaØ }

Õ are equal when used at type , because the only thing that

Ü:ÆaØ } Ü

a program can do with a record of type ß is to project out its field, and

= ÕºÜ = ¼

& . The semantics we are going to develop will allow us to argue that,

Õ ß Ü:ÆaØ }

indeed, Ô and are observationally equivalent at type , i.e., that for every

: ß Ü:ÆaØ }!ÆaØ c Ô c Õ ÆaØ closed term c , the terms and of type yield the same result. Finally, in some cases a (non-standard) semantics can be employed to establish syntactic meta-properties such as normalization or confluence.

185 January 15, 2000 22. DENOTATIONAL SEMANTICS 186

22.1 Types as Subsets of the Natural Numbers

In building semantic models of programming languages, types are commonly mod- eled as sets (or, if the language includes recursion, “domains”); closed terms are modeled as elements of the appropriate sets, open terms as functions of the in- terpretations of their free variables. For example, a straightforward model of the

simply typed lambda-calculus can be obtained by interpreting base types as arbi-

[ÆaØ]]=Æ Ë!Ì

trary sets (e.g. [ ) and each as the set of functions from

[Ë]] [[ Ì]]

[ to . : For F< , a more refined framework is required, due principally to the impredica-

tivity of the universal quantifier in System F—the fact that the bound type variable

[X]Ì 8[X]Ì in a type 8 ranges over all types, including itself. Accordingly, in a simple set-theoretic model, the first candidate for an intepretation of a universal type would be a function whose domain is the set of all sets; such a function can- not exist, for cardinality reasons. A more refined strategy would be to restrict the domain of polymorphic functions to only those sets which actually arise as inter- pretations of types in our programming language. However, Reynolds [Rey84, RP]

has shown that, no matter how we interpret universal types, there cannot exist a

!Ì model of System F in which a function type Ë is interpreted as the full set of

1

[ Ë]] [[Ì]] functions from [ to . Intuitively, what Reynolds shows is that there is a type

Ê in System F whose interpretation must be the same size as the function space

!BÓÓе!BÓÓÐ ´Ê ; the fact that no such set exists is a direct consequence of Rus-

sell’s Paradox. : The key to a successful interpretation of F< lies in the observation that the func- tions we are interested in always arise as the interpretations of finite expressions in our programming language—they are “algorithms,” not arbitrary set-theoretic functions. This means that we may restrict the interpretations of types to subsets of some a priori given universe of data values and algorithms; universal quantifiers may now be taken to range over the subsets of this set.

The Universe of Natural Numbers

A convenient choice for the universe of data values and algorithms is the set Æ of natural numbers. As is well known, all flat datatypes such as , strings, lists, floating point numbers, etc. can be encoded as natural numbers.2 We will not need to be too formal, here, about the precise encoding of algo-

rithms as numbers. We just assume that

fÒg 1. we are given some way of intepreting a number Ò as a partial function from numbers to numbers, and that

1

= 8[X] ´´´X! BÓÓе! BÓÓе ! Xµ ! X Namely Ê .

2 Ñ

Ñ; Òµ ¾ ¡ ´¾ ¡ Ò · ½µ For example, a pair ´ of numbers can be encoded as . January 15, 2000 22. DENOTATIONAL SEMANTICS 187

2. every “intuitively computable partial function” f on the natural numbers is

fÒg´Ñµ= f´Ñµ represented by some number Ò, in the sense that (where by

the equality symbol here we mean the so-called “Kleene equality”: either

Òg´Ñµ f´Ñµ

both f and are undefined, or both are defined and they are equal).

Ü: g´Üµ Ü

We write  for the number representing the function mapping each to

´Üµ g´Üµ

g , where is some concrete description of a . :

Subset Semantics for F< : We can obtain a simple semantics for F< in this setting by interpreting types as sub-

sets of Æ and terms as elements of the meaning of their types. More formally, the interpretation of simple types (i.e., the types of the simply typed lambda-calculus)

is given by the following recursive definition:

[[ ÆaØ]] = Æ

[[ ÌÓÔ]] = Æ

[[ Ë!Ì]] = fØ j 8Ü ¾ [[Ë]]: fØg´Üµ ¾ [[Ì]]g

Ð :Ì ºººÐ :Ì }]] = fØ j 8Ð ¾ fÐ :::Ð g: fØg´Ð µ ¾ [[ Ì ]]g: [[ ß

½ ½ Ò Ò i ½ Ò i i

A few comments about this definition are in order:

fØg´Üµ ¾ [[Ì]] fØg´Üµ

¯ By convention, a statement like means, in particular, that is

¾ [[Ë!Ì]] fØg

defined. Thus, if Ø , then is defined whenever it is applied to an

[ Ë]] element of [ .

In other words, although we are interpreting the elements of Æ as partial functions, the interpretations of types turn out to be functions that are total on the elements of their domains.

¯ For notational convenience, we assume that record labels are drawn from

Æ , so that records can be modeled as partial functions on numbers and field projection as application. In order to interpret types containing variables, we must parameterize the above

definition with an environment mapping type variables to subsets of Æ and (for subsequent use) term variables to natural numbers. We parameterize the above

definition by an environment 

[[ ÆaØ]] = Æ



[[ ÌÓÔ]] = Æ



[[ Ë!Ì]] = fØ j 8Ü ¾ [[ Ë]] : fØg´Üµ ¾ [[ Ì]] g

  

[[ ß Ð :Ì ºººÐ :Ì }]] = fØ j 8Ð ¾ fÐ :::Ð g: fØg´Ð µ ¾ [[ Ì ]] g

½ ½ Ò Ò i ½ Ò i i

 

and add appropriate clauses for type variables and universal types:

[[ X]] = ´Xµ



[[ 8[X<:Ë]Ì]] = fØ j 8Í  [[ Ë]] :ؾ [[Ì]] g

  ·fX7!Íg

Ì

[ Ì]]

that is, [

Í[[ Ë]] ·fX7!Íg  January 15, 2000 22. DENOTATIONAL SEMANTICS 188

Similarly we define the meaning of terms:

[[ Ü]] = ´Üµ



[[ ¼]] = ¼



[[ ×Ùcc Ø]] = [[ Ø]] · ½

 

Ò

´[[ Ø ]] µ; [[ iØeÖ Ì Ø Ø Ø ]] = [[ Ø ]] Ò =[[Ø ]]

¿ ½ ¾ ¿ ¾

where ½

   

[[ غÐ]] = f[[Ø]] g´Ðµ

 

[[ ßÐ =Ø }]] = Ð: Ð = Ð [[ Ø ]]

i i i

i if then else undefined

 

¼ ¼

[[ Ø Ø ]] = f[[Ø]] g´[[Ø ]] µ

  

[[ fÙÒ[Ü:Ë]Ø]] =  Ú: [[ Ø]]

 ·fÜ7!Úg

[[ fÙÒ[X<:Ë]Ø]] = [[ Ø]]

 

[[ Ø Ë]] = [[ Ø]]

 

[ Ø]] 

Notice that the meaning [ only depends on the restriction of to term vari- 

ables; the interpretation of types, even of those which occur as annotations in Ø,is irrelevant. Notice also that the semantics of a term may be undefined either because one of its variables is not declared in the environment or because one of the semantic ap- plications is undefined. Our aim is to formulate a soundness theorem which states that the meaning of every well-typed term is defined and is contained in the mean- ing of its type. To this end, we need to define what it means for an environment to

match a typing context.



22.1.1 Definition: Let  be an environment and be a context. Say that satisfies

j= X<:Ë ´X µ [[Ë]]

(written  ) if, whenever occurs in , we have and both defined



and the former a subset of the latter and, similarly, whenever Ü:Ë occurs in ,we

´Ü µ [[Ë]] ¾

have  and both defined with the former an element of the latter.



 22.1.2 Theorem [Soundness]: If is a context and an environment satisfying ,

then:

´ µ [[ Ë]]

1. If all the free type variables in Ë appear in dom then is defined.



` Ë<:Ì [[Ë]]  [[Ì]]

2. If then .

 

` Ø ¾ Ë [[ Ø]] [[Ë]] ¾

3. If then is an element of .

 

The proof is by induction on derivations. The most important ingredient is the following substitution lemma.

22.1.3 Lemma [Semantic substitution]:

[Ë]] [[ fX 7! ÌgË]]

1. If [ is defined, then so is and they are equal.

·fX7![[ Ì]] g 



¼

[[Ø]] [[fÜ 7! Ø gØ]] ¾

2. If ¼ is defined, then so is and they are equal.

·fÜ7![[ Ø ]] g   January 15, 2000 22. DENOTATIONAL SEMANTICS 189

Proof: By induction on types (part 1) or terms (part 2). ¾

Notice that this substitution lemma is nothing but a formalisation of the re- quirement of compositionality mentioned in the introduction to this chapter.

Proof of Theorem 22.1.2: Part (1) is by induction on types. Part (2) is by induction on subtyping derivations (not necessarily algorithmic derivations: the transitivity rule is not problematic). Part (3) is by induction on typing derivations. None of the cases in these inductions are difficult; as examples, we show the cases for function

abstraction and type application in part (3).

Ü:Ë ` Ø : Ì  j=

For the function abstraction case, suppose that ; and that .

[ fÙÒ[Ü:Ë]Ø]] = Ú: [[Ø]] d d ¾

Then [ ; call this number . We must show

 ·fÜ7!Úg

[[Ë!Ì]] ¾ [[Ë]] fdg´aµ [[Ì]]

—that is, if a , then is defined and belongs to . Now, if

  

¾ [[Ë]] fdg´aµ = [[Ø]] a ¾ [[ Ë]]

a , then . Since , the extended environment

 ·fÜ7!ag 

· fÜ 7! ag ; Ü:Ë fdg´aµ ¾

 satisfies , so the induction hypothesis applies, yielding

[Ì]]

[ , as required.



` Ø : 8[X<:Ë]Ì ` Í <: Ë

For the type application case, suppose that , that ,

j= [[ Í]]  [[Ë]] Ø

and that  . Part (2) gives us . Using the induction hypothesis on

 

[ Ø]] ¾ [[Ì]]

and the interpretation of universal types, we obtain [ . Thus, by

 ·fX7![[ Í]] g



[ Ø Í]] =[[ Ø]] ¾

Lemma 22.1.3 and the interpretation of type application, we have [

 

[fX 7! ÍgÌ]] ¾

[ .



¼

[ fÜ 7! Ø gØ]]

22.1.4 Exercise [Quick check]: How can it happen that [ is defined,



[[Ø]] ¾

but ¼ is not?

·fÜ7![[ Ø ]] g 

22.1.5 Exercise: Show the proofs of the cases for record and quantifier subtyping

for part (2) of the last proof. ¾

An application of the subset model is that it can be used to decide whether

[8[X<:ÌÓÔ]X]] = certain types are inhabited by any closed terms. For example, [

Ì 3

8[X<:ÌÓÔ]X

Í is the empty set ; so there can be no closed term of type ,

ÍÆ

because its interpretation would have to be an element of the empty set. Similarly,

[ 8[X<:ÌÓÔ]8[Y<:ÌÓÔ]´´X!Yµ!´X!Yµµ!X!Y]] the set [ —the interpretation of the type of the fixed-point combinator—is empty, which shows that the fixed-point

combinator cannot be interpreted in the subset model, and hence cannot be defined : in pure System F< . This ties in with the observation made above that all functions in the subset model are total.

3

[[Ì]]

From here on, when the environment  in an expression is empty, we will usually omit it.  January 15, 2000 22. DENOTATIONAL SEMANTICS 190

Problems with the Subset Semantics Though it validates the typing, subtyping, and evaluation relations, the subset se- mantics is unsatisfactory because it does not validate some of the rules of the re-

duction relation. More precisely, from

¼

[Ø]] =[[Ø ]] Ú ¾ [[ Ë]]

[ for all

·fÜ7!Úg ·fÜ7!Úg 

we cannot conclude that

¼

[[fÙÒ[Ü:Ë]Ø]] =[[ fÙÒ[Ü:Ë]Ø ]] :

 

[ ¼]] = ¼ =[[´fÙÒ[Ý:ÆaØ]¼µÜ]]

For instance, we have [ , but not necessarily

fÜ7!Úg fÜ7!Úg

[fÙÒ[Ü:ÆaØ]¼]]=[[fÙÒ[Ü:ÆaØ] ´fÙÒ[Ý:ÆaØ]¼µÜ]] [ , because the semantical lambda abstraction is defined on descriptions, not on actual functions. This possibility represents a failure of extensionality of the semantics. Another problem with the subset semantics is that, since subtypes are modeled as subsets, the model fails to validate some expected typed equations between

records, such as the one we saw above:

ßÜ=¼¸Ý=¼} = ßÜ=¼¸Ý=½} ¾ ß Ü:ÆaØ }

22.2 The PER interpretation

We can obtain these missing equations by endowing each type interpretation with its own “local” notion of equality. In the case of function types, this equality will be defined in such a way that algorithms that map equal arguments to equal results are regarded as equal. (This will solve both of the problems observed at the end of the previous Section, since records are interpreted as partial functions on labels.)

22.2.1 Definition: A partial equivalence relation (PER) is a symmetric and transi- ¾

tive relation (not, in general, reflexive) on the set Æ of natural numbers.

Ñ Ò Ê Ê

We write ÑÊÒ when and are related by ; alternatively, we can view as

¢ Æ ´Ñ; Òµ ¾ Ê Ê ´Êµ

a subset of Æ and write . When is a PER, we write dom for

Ò j ÒÊÒg Ê Ê

the set f , the set of numbers related to themselves by . Notice that is

ʵ

an equivalence relation on dom´ , so a PER can be thought of as consisting of a ÜÊÝ

subset of Æ together with a local equality relation. Also, note that if then both

Ý ´Êµ

Ü and are in dom .

Ë Ê  Ë Ê Ë

If Ê and are PERs, we write to mean that is a subrelation of in the

ÜËÝ ´Ëµ

set-theoretic sense—i.e., ÜÊÝ implies . This means that dom is a superset of

ʵ Ë Ê dom´ and that the equality in on the common part is coarser than the one in . This will account for the “non-injective” nature of the subtyping relation between

record types (the fact that two different records in a type Ë can become equal when

viewed at a supertype Ì). January 15, 2000 22. DENOTATIONAL SEMANTICS 191

Interpretation of Types

 : The types of F< are interpreted as PERs as follows. (The environment here as- signs PERs, not just sets of numbers, to type variables—and, as before, natural

numbers to term variables.)

[[ ÆaØ]] = f´Ò; Òµ j Ò ¾ Æ g



[ ÌÓÔ]] = Æ ¢ Æ

[ (the everywhere-true relation)



¼ ¼ ¼ ¼

[[ Ë!Ì]] = f´Ø; Ø µ j 8´Ü; Ü µ ¾ [[ Ë]] : fØg´Üµ[[Ì]] fØ g´Ü µg

  

¼ ¼

[[ ß Ð :Ì ºººÐ :Ì }]] = f´Ø; Ø µ j 8Ð ¾ fÐ :::Ð g: ´fØgÐ ; fØ gÐ µ ¾ [[Ì ]] g

½ ½ Ò Ò i ½ Ò i i i

 

¼ ¼

Í  [[Ë]] g [ 8[X<:Ë]Ì]] = f´Ø; Ø µ j Ø[[Ì]] Ø

[ for all

  ·fX7!Íg

Ì

[ Ì]]

that is, [

Í[[ Ë]] ·fX7!Íg



¾ ´[[ Ë!Ì]] µ f[[Ë!Ì]] g

22.2.2 Exercise [Quick check]: Show that, if f; g dom , then

 

´aµ[[Ì]] g´aµ a ¾ ´[[ Ë]]µ ¾

iff f for all dom .  The interpretation of terms is exactly as in the subset interpretation in Sec- tion 22.1. To show that this interpretation is sound, we must slightly modify the

definition of satisfaction between environments and contexts: when Ü:Ë is a bind-

´Üµ ¾ ´[[ Ë]] µ

ing in , we require that dom . 

22.2.3 Theorem [Semantic soundness of the PER intepretation]: The PER interpre-

j= tation is sound in the sense that all statements are validated semantically. If  ,

then:

` Ë <: Ì [[Ë]]  [[Ì]]

1. implies ;

 

` Ø : Ë [[Ø]] ¾ ´[[Ë]] µ

2. implies dom ;

 

£ ¼ ¼ ¼

! Ø ` Ø : Ì ` Ø : Ì [[Ø]] [[ Ì]] [[ Ø ]] ¾

3. Ø , with and , implies .

   Proof: Exercise. The argument is similar to the proof of 22.1.2. First, one estab- lishes the validity of the semantic substitution lemma, replacing subsets by PERs. The proofs then proceed by induction on derivations. In part (2), the statement

must be strengthened as follows:

¼ ¼

j=  j= ´Xµ= ´Xµ X

2’. If  and , and if for all type variables declared in

¼

´Üµ[[ Ë]]  ´Üµ Ü:Ë ` Ø : Ë

and for all term variable declarations , then



[[Ø]] [[ Ë]] [[ Ø]]

implies ¼ .

  

[[Ë]] =[[Ë]] ¾

Notice that ¼

  One technical note is in order. Strictly speaking, the PER semantics does not model reduction as equality, but rather as relatedness in a certain PER. If one de- sires actual equality, one can decree that the meaning of a term is not a natural number, but rather an equivalence class of natural numbers; then, however, the meaning of a term depends on its type, which makes the interpretation of subtyp- ing more complicated. January 15, 2000 22. DENOTATIONAL SEMANTICS 192

Applications of the PER model Now we come to the promised application of the PER model as a means to estab- lish observational equivalence of programs. The main idea is that, at the atomic

type ÆaØ, the semantic equality agrees with the syntactic equality given by the re-

duction relation.

Ø Ø ÆaØ [[Ø ]][[ÆaØ]][[Ø ]]

¾ ½ ¾

22.2.4 Lemma: If ½ and are closed terms of type , then im-

Ø Ø ¾ ¾

plies that ½ and have the same number as normal form. :

Proof: By the strong normalization of System F< (Theorem ??) together with preser-

Ø Ø ¾ vation (??), ½ and each have some number as normal form. By the soundness

theorem (22.2.3, part 3), the interpretation of a term is related to the interpretation

Ø Ø [[ÆaØ]] ¾ of its normal form, so the normal forms of ½ and are related by , hence

equal. ¾ : The proof of this lemma relies heavily on the strong normalization of F< .An analogous property also holds in the absence of strong normalization (e.g., in the presence of the fixed-point operator). Here, one must show that, if the interpreta- tion of a term is a number, then the term admits a reduction to this number.

22.2.5 Exercise: Give this argument in detail. ¾

Ø Ø Ë ¾ 22.2.6 Definition: Two closed terms ½ , of type are observationally equiva-

obs obs

Ë Ø = Ø Ë Ø = Ø

Ë ¾ ½ ¾

lent at type (written ½ or, when is clear from context, just ) if,

c : Ë!ÆaØ c Ø c Ø ¾ for every closed term , it holds that ½ and reduce to the same

number. ¾

obs

Ø = Ø Ø Ø

¾ ½ ¾ The idea is that ½ means that and can be replaced by one another in an arbitrary program, since the visible output of a program must be a number.

22.2.7 Remark: This rather simple definition of observational equivalence relies on the fact that there is a distinguished atomic type in which to make observations and on the fact that open terms can be treated as closed terms using functional ab-

straction (so that we can regard every term containing Ø as a subphrase is equal to

Ø Ø c an term of the form c , where does not occur in ). In more complex languages where other binders are available, it may be necessary to extend the notion of ob- servational equivalence to so-called contextual equivalence, where the observing context is a term with a hole somewhere inside it. In particular, such a context may

bind free variables in the observed term. ¾

Ø Ø ¾ 22.2.8 Theorem [Computational adequacy]: Let ½ and be closed terms of a

obs

Ë [[Ø ]][[Ë]][[ Ø ]] Ø = Ø ¾

¾ ½ Ë ¾ closed type .If ½ , then .

January 15, 2000 22. DENOTATIONAL SEMANTICS 193

Ø ; Ø : Ë [[Ø ]][[ Ë]][[Ø ]] c : Ë!ÆaØ [[c]] ¾ ´[[ Ë!ÆaØ]]µ

¾ ½ ¾ Proof: Suppose ½ and .If , then dom .

Thus,

[[c Ø ]]=f[[c]] g´[[Ø ]]µ [[ÆaØ]] f[[c]]g´[[ Ø ]]µ = [[ c Ø ]] :

½ ½ ¾ ¾

c Ø c Ø ¾ Hence, by Lemma 22.2.4, ½ and must have the same number as normal

obs

Ø = Ø ¾ ¾ form, and ½ .

The computational adequacy theorem shows how the PER model can be employed =

to reason about observational equivalence. For example, the two records Ô

Õ = ßÜ=¼¸Ý=½} ß Ü:ÆaØ }

ßÜ=¼¸Ý=¼} and are observationally equivalent at type .

[ Ô]][[ß Ü:ÆaØ }]][[Õ]] f[[Ô]] g´Üµ=f[[ Õ]] g´Üµ To see this, note that [ , since .

22.2.9 Exercise [Recommended]:

obs

e f e = f

1. Show that if and are closed, well typed terms, then ÌÓÔ .

obs

` Ô : Ì Ì = ß Ð :Ì ºººÐ :Ì } Ô =

½ Ò Ò Ì

2. Show that whenever where ½ , we have

ßÐ =ԺРºººÐ =ԺР} ¾

½ Ò Ò ½ .

We now investigate observational equivalence at polymorphic types. As we

did with the subset semantics, we can use the PER semantics to argue that types

[8[X] 8[Y] ´´X!Yµ!´X!Yµµ!X!Y]] such as [ are empty (showing that no fixed- point operator can be defined). Unlike the subset model, though, the PER model can also be used to constrain the elements of inhabited universal types, validating

some useful principles of uniformity.

Øg´Òµ

22.2.10 Notation: To reduce clutter in the following, we will often abbreviate f

Ø´Òµ ¾

by ØÒ or .

Í = [[8[X<:Ë]X!X]] f ¾

22.2.11 Proposition: Let Ë be an arbitrary type and .If

͵ fÍÜ: Ü ¾

dom´ , then .

 [[Ë]] Ü ¾ ´Xµ

Proof: We must show that, for every PER X and every dom , we have

´Üµ XÜ f ¾ ´Íµ Y  [[Ë]] Ü ¾ ´Y µ

f .From dom , we know that, for each PER and dom ,

´Üµ ¾ ´Y µ X  [[Ë]] Ü ¾ ´Xµ Y  X  [[ Ë]]

we have f dom . Suppose that and dom . Choose

´Ü; ܵg Ü ¾ ´Y µ f´Üµ ¾ ´Y µ f´Üµ=Ü

to be the singleton f .From dom we infer dom ,so .

´Üµ XÜ Ü ¾ ´Xµ ¾ Thus, f for every dom .

Notice that this excludes the possibility of “polymorphically updating” fields

of records in the PER model; for example, it follows by a similar argument that

[X<ßÜ:ÆaØ}]ÆaØ!X ÆaØ every function of type 8 must discard its argument and

return its X argument unchanged. In particular, such a function cannot have the

effect of replacing the Ü field in its first argument by the number given as its sec- ond argument. Also, notice that, by computational adequacy, every closed term January 15, 2000 22. DENOTATIONAL SEMANTICS 194

of this type must be observationally equivalent to such a constant function. Poly- : morphic update can be supported by extending the syntax of F < , as we shall see in Chapter 23, but such extensions cannot be interpreted in the PER model as it stands; it is, however, possible to construct a more refined PER model, using a different interpretation of subtyping, in which polymorphic update functions do exist [HP95, Pol96, ?]. Next we examine the interpretations of impredicative encodings of algebraic datatypes, such as the Church booleans and Church numerals introduced in Sec-

tion 18.4.

[ 8[X] X!X!X]] = Ü: Ý: Ü

22.2.12 Proposition: Let CBool be the PER [ . Let tt and

Ü: Ý: Ý ; ¾ ´ µ f ¾ ´ µ

ff = . We have ff tt dom CBool and, whenever dom CBool , either

f ¾

f CBool tt or CBool ff.

¼ ¼

¾ ´ µ Ü X Ü Ý X Ý

Proof: First, recall that f dom CBool means that and imply

¼ ¼ ¼ ¼

Ü Ý X f Ü Ý X Ü; Ü ;Ý;Ý Ü; Ý ¾

f , for every PER and numbers . In particular, if

Xµ fÜ Ý ¾ ´Xµ

dom´ , then dom .

= f´¼; ¼µ; ´½; ½µg ´Xµ = f¼; ½g f¼½ ¾

Now consider the PER X , with dom . Since

Xµ f¼ ½ = ¼ f¼½= ½

dom´ , we have either or . Suppose, without loss of generality,

= ¼ f ØØ Ü Ý

that f¼½ . We claim that, in this case, CBool . Letting and be natural

= Ü

numbers, we must show that fÜÝ . Using the same argument as before, with

½ Ü Ý fÜÝ ¾ fÜ; Ýg Ü = Ý fÜÝ= Ü

¼ and replaced by and , we find that .Soif , then Ý and we are done. Suppose, on the other hand, that Ü and are different. There are

several cases to consider.

Ü Ý ¼ ½ X

¯ Suppose and are both different from and . Let be the PER with

Ü; ¼g fÝ; ½g

equivalence classes f and —i.e.,

X = f´¼; ¼µ; ´¼; ܵ; ´Ü; ¼µ; ´Ü; ܵ; ´½; ½µ; ´½; ݵ; ´Ý; ½µ; ´Ý; ݵg:

ÝX½ ´fÜݵ X ´f¼ ½µ ´fÜݵ X¼ fÜÝ= Ü

From ÜX ¼and , we get so and ,

Ü Ý ¼

using the fact that fÜÝis either or , hence not .

Ü ¼ X f¼g fÝ; ½g

¯ Suppose is . Let be the PER with equivalence classes and .

6= Ý

Since Ü , these two classes are different. Reasoning as before, we have

fÜݵ X¼ fÜÝ = ¼ = Ü

´ ,so .

Ü = ½ Ý = ¼ X f¼; ¾g

¯ Suppose and . Let be the PER with equivalence classes and

½g Y f¼; ½g f¾g ¾ X ¼

f and let be the PER with equivalence classes and .From

f¾½ = ¾ ¾Y¾ ¼Y½ f¾ ¼= f¾½ = ¾

and ½X ½, we obtain .From and , we get .

f½; ¾g f¼g ´f½ ¼µZ´f¾¼µ

Finally, using Z with classes and ,weget , and hence

¾ f½; ¾g fÜݾ fÜ; Ýg f½ ¼= ½ f½ ¼ . Since , we conclude that .

The other cases are left as exercises. ¾ January 15, 2000 22. DENOTATIONAL SEMANTICS 195

Similar in spirit but more complex is Freyd’s proof that every element of the

[ 8[X] ´X!Xµ!X!X]] type [ must be related to the interpretation of a Church nu- meral [Fre89]. The above characterisation of Church booleans would be much easier if we

were allowed to use arbitrary relations, not just PERs—if it were the case, for exam-

¼ ¼ ¼ ¼

¾ ´ µ ´fÜݵ Ê ´fÜ Ý µ ÜÊÜ ÝÊÝ

ple, that f dom CBool implied whenever and for

¼ÊÜ ½ÊÝ some relation Ê. We could then directly use the relation defined by and and wouldn’t need any case distinctions. A model in which such relation based reasoning principles are valid for arbitrary polymorphic types (not only booleans) is called parametric [Rey83, ?]. In a parametric model, very powerful principles for polymorphic encodings of inductive types and abstract datatypes are available (cf. [PA93]). However, it is an open problem whether the PER model is parametric, and the only known parametric models are rather syntactic in flavor. However, some simple instances of parametric reasoning do go through in the

PER model.

¾ [[8[X]X!Ë]] X Ë f

22.2.13 Proposition: Let f , where is not free in . Then is constant—

Ü ¾ ´Xµ ´fܵ[[ Ë]]´f¼µ ¾

that is, for each PER X and element dom , we have .

[ ÌÓÔ]] Ü Ü [[ ÌÓÔ]] ¼

Proof: Using the everywhere true relation [ . (Let be given. Then ,

fܵ[[ Ë]]´f¼µ ¾ so ´ .)

The above example is a a simple case of representation independence. One

¾ [[ 8[X]X!A]] can view f as a piece of code depending on a module that supplies

a type X and a constant of that type. (Think of the encoding of existential types in terms of universal types sketched in Exercise ??.) If there are no other constants or functions defined on this type, then intuitively it should not be possible to make any use of it. The PER model validates this intuition. Here is another reasoning principle based on the observation that the PER se-

mantics uses neither type annotations nor type applications or abstractions. : 22.2.14 Reasoning Principle [Mitchell]: Any two F < terms of the same type and with equal erasures are observationally equal.

For example, if

f : 8[X] ´X!Xµ ! ´ÆaØ!Xµ ! X

Î <: ÌÓÔ

Í <: Î

g : Î!Í

h : ÆaØ!Í; then

obs

f Í ´fÙÒ[Ù:Í]g´Ùµµ´hµ = f Î ´fÙÒ[Ú:Î]g´Úµµ´hµ:

Î ¾

Proof: Exercise. ¾ January 15, 2000 22. DENOTATIONAL SEMANTICS 196

Digression on full abstraction One may ask whether the reasoning method arising from Theorem 22.2.8 is com-

obs

Ø = Ø [[×]] [[Ø]] ¾ plete, i.e., whether ½ implies = . Semantic models for which this is the case are called fully abstract. It is an open problem (as far as we know) whether

the PER model is fully abstract, but it seems unlikely for the following reason. ×

We might attempt to prove full abstraction by induction on the type Ë of and

Ë = ÆaØ Ë!Ì Ø.If , then it clearly holds; but for the function space we encounter the

obs

f; g : Ë!Ì f = g [[f]]=[[g]]

following problem. Suppose ` and . To prove , we have

[f]]´Úµ [[Ì]] [[g]]´Úµ Ú ¾ ´[[ Ë]]µ

to show that [ for all dom . Using full abstraction induc-

[[f]]´Úµ[[ Ì]][[ g]]´Úµ Ú [[Ø]]

tively on Ì, we get for all definable , i.e., those of the form for

Ø : Ë ´[[ ÆaØ!ÆaØ]]µ some ` . But even dom contains non-definable elements (since

it contains all total computable functions, and some of these cannot be defined4 : in F< ). It could, however, be that every non-definable element is observationally equivalent to a definable one, in which case we could salvage this argument.

22.3 General Recursion and Recursive Types

Although the PER semantics is based on arbitrary computable functions, only the total ones actually arise as denotations. In order to account for general recursion and recursive types, we need a more generous notion of model.

Continuous Partial Orders We have already seen that the PER model does not account for general recursion—

although the elements of the underlying universe (Æ ) encode partial functions, the interpretations of types include only elements encoding functions that are total on the relevant domain. There does not seem to be an easy way of removing this

restriction: if we insist on interpreting types as PERs over Æ , our model will ac- count only for total functions. To model recursive types (and accordingly, general recursion and higher-order partial functions), we must adopt a richer view of the underlying computations. The required machinery comes from the mathematical

area of domain theory.

D; Úµ D 22.3.1 Definition: A domain is a partial ordering ´ (that is, a set with a

transitive, reflexive, and anti-symmetric ordering Ú) with the following properties:

Ü Ú Ü Ú Ü Ú ::: D

½ ¾

1. If ¼ is an increasing chain in then there exists a least upper

F F

Ü ¾ D Ü Ú Ü i Ü Ú Ý i

i i i

bound i . That is, for all and, if for all , then

i i

F

Ü Ú Ý

i . i

4

´f µ

Ü

¾Æ

This can be seen from a simple diagonalization argument. Suppose that Ü is an effective

ÆaØ! ÆaØ Ü: f ´Üµ·½

Ü :

enumeration of all closed F< terms of type . Then is a computable function that : is not definable in F < .

January 15, 2000 22. DENOTATIONAL SEMANTICS 197

D ? ? ¾

2. has a least element (written or D and pronounced “bottom”).

22.3.2 Exercise [Easy]: Show that the least upper bound of each chain in a domain

D Ü Ú Þ i Ü Ú Ý i

is uniquely determined, in the sense that, if i for all and, whenever

F

i Þ Ú Ý Þ = Ü ¾

for all , we have , then i . i

The structures we call domains are often called “omega-complete partial or- ders (with bottom),” reserving the word “domain” for structures satisfying further

properties such as “algebraicity” or “continuity.”

E [D!E]

Let D and be domains. We define the space of continuous functions

E f ¾ D ! E from D to as the set of monotone functions that preserve suprema,

i.e.,

Ü Ú Ý f´Üµ Ú f´Ýµ

¯ implies , and

F F

¯ f´ Ü µ= f´Ü µ ´Ü µ

i i i¾Æ

i for every increasing chain .

i i

! E

D can be viewed as a domain itself by ordering its elements pointwise, i.e.,

Ú g f´Üµ Ú g´Üµ Ü ¾ D f iff for all . The bottom element and least upper bounds

in this domain are also calculated pointwise. Note that we do not require that the

[D!E] ? ? E

elements of should be strict (i.e., map D to ).

¾ [D!D]

22.3.3 Proposition: Every continuous function f has a fixed point given

f´?µ Ú f´f´?µµ Ú ::: ¾ as the least upper bound of the chain ?Ú

Proof: Exercise. ¾

22.3.4 Definition: Let Ä denote the set of natural numbers considered as record la-

bels. (For technical convenience, we continue using numbers as labels.) We define

Dµ f ¾ Ä ! D

Rcd´ as the set of functions , ordered pointwise, plus a distinguished ?

least element ? (usually written just ). Again, this forms a domain.

Rcd´

Dµ ? We will use Rcd´ to interpret record types. The addition of the element

allows us to distinguish a nonterminating computation of record type (such as

ß } fÙÒ[Ö:ß }] Ö fiÜ ) from a record containing an undefined (nonterminating)

field (such as ßÐ=ÓÑega}). This reflects the fact that the call-by-name evaluation relation does not evaluate within the fields of a record, but waits until a field is

projected to evaluate it further. ¾ Æ

22.3.5 Definition: The flat domain of natural numbers ? has as elements the

Ü Ú Ý Ü = ?

natural numbers plus an extra bottom element ?. The ordering is: iff

= Ý ¾ or Ü .

As before, types will be interpreted as partial equivalence relations. Instead of the natural numbers, though, the underlying universe of these PERs will be the

domain that forms the least solution of the following equation:



Æ · [D!D] · D ´Dµ = ? Rcd January 15, 2000 22. DENOTATIONAL SEMANTICS 198

That is, we will use a domain D that “contains” the flat domain of natural numbers,

D!D] ´Dµ the function space [ , and the record domain Rcd . Rather than developing a general theory of such equations and their solutions, we simply assert (without proof) the existence of a suitable domain and list its relevant properties:

22.3.6 Proposition: There exists a domain D with functions

?

Æ ¾ [Æ ! D] Æ ¾ [D ! Æ ]

? ?

?

[[D!D] ! D] ¾ [D ! [D!D]]

fun ¾ fun

?

¾ [D ! [ ´Dµ ! D] ´Dµ]

rcd ¾ Rcd rcd Rcd

fÆ ; ; g

satisfying the following equations (for ¥¾ fun rcd )

?

¥´¥ ´Üµµ = Ü

¥´?µ= ?

D

¬

e d = ¥´eµ e

? if for some

¥ ´dµ=

? otherwise

¾ D d = ¥´eµ e

and such that every element d can be expressed as for some , where

fÆ ; ; g ¥ is one of fun rcd . Furthermore, there is an increasing sequence of projection

functions

 ¾ [D ! D] Ö ¾ Æ

Ö for all

with the following properties:

 ´dµ Ú d

1. Ö

 ´ ´dµµ =  ´dµ

Ö ×

Ö;×µ

2. min´

 ´dµ=?

3. ¼

F

 ´dµ=d

4. Ö Ö

def

D = fd j  ´dµ=dg Ö

5. Ö is a finite set

 D

6. the projections Ö are compatible with the structure of in the following

sense:

¬

´Òµ Ò  Ö

Æ if

 ´Æ ´ Òµµ =

·½ (a) Ö

? otherwise

 ´ ´fµµ = ´Ü:  ´f´ ´Üµµµµ

·½ Ö Ö

(b) Ö fun fun .

 ´ ´fµµ = ´Ð: Ð  Ö  ´f´Ðµµ ?µ ¾

·½ Ö (c) Ö rcd rcd if then else

Proof: See [Gun92] or any other standard text on domain theory. ¾

January 15, 2000 22. DENOTATIONAL SEMANTICS 199

D Æ ´Dµ

In other words, has ? , Rcd , and—in particular—its own function space

D!D] D

[ as “subdomains,” and is obtained as the “limit” of an increasing se-

D  Ö quence of finite subsets—the ranges Ö of the . These approximating subdo- mains can be explicitly constructed by taking the clauses under (6) as an inductive

definition. In particular,

D = f?g

¼

D = f?; Æ ´¼ µ; ´Ð: ?µg

½ rcd

D = f?; Æ ´¼ µ; Æ ´½ µ;

¾

Ð: ?µ; ´¼ 7! Æ ´¼ µ; Ð>¼ 7! ?µ; ´¼ 7! Æ ´¼ µ; ½ 7! Æ ´ ¼µ; Ð>½ 7! ?µ;

rcd´ rcd rcd

¼ 7! ´Ð: ?µ;½7! ´Ð: ?µ;

rcd´ rcd rcd

7! ?µ; :::;

Ð>½ and 5 more records

´Ü ¾ D : Æ ´¼µµ; ´Ü ¾ D :ܵ; ::: g ½ fun ½ fun and 8 more functions etc.

22.3.7 Exercise: D

1. How many elements does ¿ contain?

D f ´dµ j d ¾ Dg Ö

2. Convince yourself that Ö can be described as . 

3. Describe explicitly the action of the projection ½ viewed as a function from

D D ¾ ½ ¾ to .

22.3.8 Exercise [Recommended]: D 1. Call a domain D finitary if every increasing chain in contains a finite num-

ber of elements. Show that, if D is finitary, then the least upper bound of

every increasing chain in D is an element of the chain. Does this implication

hold in the other direction?

Æ D Ö

2. Note that ? and each are (trivially) finitary. Give an example of an

[Æ !Æ ] ?

increasing chain with infinitely many distinct elements in ? .

F

Ü Ú Ü Ú ::: D  ´ Ü µ =

½ Ö i

3. Consider an increasing chain ¼ in . Show that

i

 ´Ü µ j ¾ j

Ö for some .

[D!D]

22.3.9 Exercise: Give an explicit definition of a continuous function succ ¾

Æ ´ Òµµ = Æ ´Ò · ½µ ¾ with the property that succ´ . January 15, 2000 22. DENOTATIONAL SEMANTICS 200

The CUPER Interpretation

As before, we will interpret types as “subsets of D equipped with local notions of

equality”—i.e., PERs over D. However, in order to interpret general recursion and recursive types, some additional conditions will be needed.

1. In order to ensure that the fixed-point functional described in Exercise ??

def F

i

´fµ = f ´?µ ´[[8[X]´X!Xµ!X]]µ

(which sends f to fix ) will be an element of dom ,

i

?; ?µ we require that every PER used to interpret types contains the pair ´ and

is closed under least upper bounds of increasing chains. (Informally, if Ê is

such a PER and f sends R-related elements to R-related elements, then from

i i

Ê ? f ? Êf ? i ´fµ ¾ ´Êµ ? we see by induction that for every . Hence fix dom .) This condition is called completeness. 2. In order to interpret recursive types, we must further require that the PERs

used to interpret types be determined by their restrictions to the finite sets D

Ö . This condition is called uniformity.

22.3.10 Definition: A complete uniform PER (CUPER) is a symmetric, transitive D

relation Ê on such that:

Ê ?

1. ? .

´Ü µ ´Ý µ Ü Ê Ý i

i¾Æ i i¾Æ i i

2. If i and are two increasing chains such that for all ,

F F

Ü Ê Ý i

then i (completeness).

i i

ÜÊ Ý  ´Üµ Ê ´Ýµ Ö ¾ Ö 3. iff Ö for all (uniformity).

22.3.11 Exercise: There is some redundancy in this definition: we can either drop

(2) or replace the “iff” in (3) by “implies.” Show this. ¾

22.3.12 Definition:

f´Æ ´Òµ; Æ ´ Òµµ j Ò ¾ Æ g

1. The CUPER Nat is defined by ? .

¢ D

2. The CUPER Top is the total relation D .

Ë Ê µ Ë

3. When Ê and are CUPERs, the CUPER is defined by

´ ´fµ; ´gµµ j Ü; Ý ¾ D ÜÊÝ f´Üµ Ëg´Ýµ g

f fun fun for all ,if then .

Ê Ê Ð :::Ð fÐ :Ê :::Ð :Ê g

Ò ½ Ò ½ ½ Ò Ò

4. If ½ through are CUPERs and are labels, then the CUPER

f´?; ?µg[f´ ´fµ; ´gµµ j f; g ¾ Ä!D f´Ð µ Ê g´Ð µ i = ½:::Òg

i i

is defined by rcd rcd and i for .

Á ´Ê µ Á

i¾Á

5. Let be any set and i be an -indexed family of CUPERs. The CUPER

Ì Ì

Ê Ê Ü Ê Ý ÜÊ Ý

i i i

i is defined as the intersection of all the , i.e., iff for

i i

¾ Á all i .

(When we use this definition below, the index set Á will always be the set of sub-CUPERs of some CUPER.)

January 15, 2000 22. DENOTATIONAL SEMANTICS 201

f´?; ?µg ¾ 6. ? is the CUPER .

22.3.13 Exercise [Recommended]: Show that all of these constructions actually de-

fine CUPERs. ¾

These constructions on CUPERs allow us to define a semantics that maps types

D : of F< (without recursive types) to CUPERs and maps terms to elements of ly- ing in the domains of their types, using essentially the same definition as in Sec-

tion 22.2 (the interepretations of both types and terms are with respect to an en-

[ 8[X] ´X!Xµ!X]]µ

vironment, as before). In this semantics, the type dom´[ is non-

¾ [D!D] empty; in particular, it contains the function that sends f to its least fixed

point. Other elements of this type are finite approximations of the fixed point, i.e.,

Ò

f ´?µ Ò functionals mapping functions f to for some . It remains to show how to interpret recursive types.

Interpreting Recursive Types

Ê Ö ¾ Æ Ê

22.3.14 Definition: Let be a CUPER and . We write Ö for the restriction

Ê D ÜÊ Ý ÜÊÝ  ´Üµ=Ü  ´Ýµ=Ý ¾

Ö Ö Ö

of to the finite set Ö , i.e., iff and and .

Ê = ? Ê Ê Ê

Ö Ö·½

Notice that ¼ and is a sub-CUPER of and , for each CUPER

Ê Ë

Ê. Also note that, by the uniformity condition, two CUPERs and are equal iff

Ê = Ë Ö ¾ Æ Ö Ö for all .

22.3.15 Definition: A function F mapping CUPERs to CUPERs is called contrac-

Ê Ö ¾ Æ F´Êµ = F´Ê µ F

·½ Ö Ö·½

tive if, for each CUPER and we have Ö . is called

F´Êµ = F´Ê µ ¾

·½ Ö·½ Ö·½

nonexpansive if Ö .

F F F´Ê µ =

·½ Ö·½

Note that “ contractive” implies “ non-expansive,” since Ö

F´Ê µ  = F´Êµ j = F´Êµ

·½ Ö·¾ Ö·½ Ö·¾ Ö·½ Ö·½

Ö .

F´Êµ=Ê µ Æ

22.3.16 Exercise [Recommended]: Show that ? is contractive. Give

an example of a nonexpansive function on CUPERs that is not contractive. ¾

22.3.17 Definition: Let F be a contractive function mapping CUPERs to CUPERs.

Ö

´Fµ Ü´Fµ Ý  ´Üµ F ´?µ  ´Ýµ Ö ¾ Ö

The CUPER is defined by iff Ö for all .

Ö

´Fµ = F ´?µ ¾ Ö

22.3.18 Lemma: Ö .

Ö

´Fµ  F ´?µ Ö Proof: The direction Ö is immediate from the definitions. For the

other direction, we first establish

k·½ k

F ´?µ = F ´?µ k ¾ Æ k k for all (22.1)

January 15, 2000 22. DENOTATIONAL SEMANTICS 202

k·½ k k

F ´?µ = F ´F´?µ µ = F ´?µ

¼ k k

by calculating as follows: k . The penulti-

 k F mate step follows by “commuting” k with applications of , reducing the index

by ½ at each step using contractiveness.

Ö k·½ k·½

ÜF ´?µ Ý Ü; Ý ¾ D F ´?µ  F ´?µ =

Ö k·½ k

Now assume that Ö , hence, .From

k k

F ´?µ  ´ÜµF ´?µ  ´Ýµ k  Ö

k k k

we obtain inductively that k for all . (Note that

 ´Üµ= ´ ´Üµµ =  ´Üµ=Ü

k Ö Ö

k .)

Ö

 ´ÜµF ´?µ  ´Ýµ

¹½ Ö¹½ Ö¹½

On the other hand, Ö by uniformity, hence

Ö¹½

 ´ÜµF ´?µ  ´Ýµ

Ö¹½ Ö¹½ Ö¹½

k

 ´ÜµF ´?µ  ´Ýµ

k k

by Equation 22.1. Proceeding inductively in this way yields k ¾

for all k<Ö.

´Fµ F F´´Fµµ = ´Fµ

22.3.19 Proposition:  is the unique fixed point of , that is, and,

´Êµ=Ê Ê = ´Fµ ¾

if F then .

´Fµ F ´Fµ =

·½

Proof: To show that is a fixed point of , it suffices to show that Ö

F´´Fµµ Ö ¾ Æ F F´´Fµµ = F´´Fµ µ =

Ö·½ ·½ Ö Ö·½

for all . Now, since is contractive, Ö

Ö Ö·½

F´F ´?µ µ = F ´?µ = ´Fµ

Ö·½ Ö·½ Ö·½ Ö (using Lemma 22.3.18 in the second

step and the definition of contractiveness in the third step). On the other hand, if

F´Êµ=Ê Ê = ÑÙ´Fµ Ö Ö = ¼ ? Ö

, we can show Ö by induction on .If , both sides are .

Ê = F´Êµ = F´Ê µ = F´´Fµ  = ´Fµ

·½ Ö·½ Ö Ö·½ Ö Ö·½ Ö·½ Otherwise, we have Ö ,

where the induction hypothesis is used in the penultimate step. ¾

22.3.20 Proposition: All functions on CUPERs definable from the operations in

Definition 22.3.12 plus  are nonexpansive; they are contractive if their outermost

operation is record formation or function space formation. ¾

Proof: Straightforward induction (see [AC96]). ¾

22.3.21 Exercise [Possibly difficult]: We believe that the only nonexpansive but not contractive function that can be constructed using these operators is the iden-

tity. Prove or refute this claim. ¾

It follows that, if a function F on CUPERs is definable from the operations in

G Ê µ

Definition 22.3.12 plus , then the function mapping each CUPER to Top

´Êµ F is contractive. This enables us to interpret recursive types by adding the fol-

lowing semantic clauses:

[ ´XµÌ]] = ´Ê: => [[Ì]] µ

[ Top

 ·fX7!Ê g

´d: ´Ü: dµµ [ fÓÐd ´´XµÌµ]] =

[ fun fun



?

´d: [ ÙÒfÓÐd ´´XµÌµ]] = ´dµ´¼µµ

[ fun fun



[´XµÌ]] = µ [[fX 7! ´XµÌgÌ]]

For the last two clauses, we use the fact that [ Top ,

  which follows from Proposition 22.3.20 and an appropriate substitution lemma. January 15, 2000 22. DENOTATIONAL SEMANTICS 203

This semantics shows us (somewhat trivially) that the reduction rules for the

system including recursive types do not equate different natural numbers. It also

: shows the soundness of an equational theory for F< including additional equa-

tions like

fÓÐd ´´XµÌµ ´ÙÒfÓÐd ´´XµÌµ ص = Ø ¾ ´XµÌ:

: An appropriate definition of observational equivalence for F < must deal with

the possibility of nontermination—for example, as follows:

Ø Ø Ì ¾

Two closed terms ½ and of type are observationally equivalent

Ì C : Ì!ÆaØ C Ø C Ø ¾ (at type ) if, for all closed terms , the terms ½ and either both diverge (i.e., admit no normal form) or can be reduced to the same number. Computational adequacy of the CUPER semantics with respect to this notion of

equivalence now becomes a nontrivial result. We must show that, if Ñ is a closed

[[ Ñ]] = ? Ñ term of type ÆaØ, then iff has no normal form. One direction is trivial (which?). The other requires a “logical relations” proof, i.e., an induction over terms using a suitable generalization of the desired property for types other than

ÆaØ. (We are not aware of such a proof in the literature, but there seem to be no major obstacles.)

22.4 Further Reading

The subset and PER models of the simply typed lambda-calculus are due to Kreisel, who called them HRO (“hereditarily recursive operations”) and HEO (“hereditar- ily effective operations”), respectively. A good reference with pointers to related topics of historical interest is Troelstra and van Dalen’s book [TvD88]. A standard reference on PER models in a computer science context is Mitchell’s book [Mit96]. Our presentation of CUPERs is a simplified version of the one used by Abadi and Cardelli [AC96]. Other treatments of CUPERs can be found in [?, ?] The concept of full abstraction was introduced by Plotkin in [Plo77], which

is still well worth reading. Recent progress in the construction of fully abstract : models (albeit not yet for F< ) is reported in [AJM94, HO94, OR94]. Parametricity was first studied by Reynolds in the context of representation

independence [Rey83]. Parametric models of System F are described in [BFSS90, : RR94]. Parametricity in System F < is considered in [CMMS94]. Good general textbooks on semantics include [Sch86, Gun92, Ten81, Win93, Mit96]. Chapter 23

Polymorphic Update

This chapter is just a sketch. The mechanism of polymorphic update is quite a bit less “mainstream” than almost all of what’s covered in the rest of the chapters. It’s not completely clear that it belongs. On the other hand, it makes the object encoding examples in Chapter 28 vastly clearer. In fact, I’m tempted to go even further and introduce an ad-hoc “in place update” operation for existential types (following a suggestion in [HP98]). This makes it possible

to do the whole of Chapter 28 in a second-order setting, before discussing type operators.

fg : Polymorphic update F < + update

New syntactic forms

Ø ::= ... (terms...)

i¾ ½::Ò

} ß  Ð =Ø

i i

i record

Ð=Ø Ø field update

Ì ::= ... (types...)

i¾ ½::Ò

ß  Ð :Ì }

i i

i type of records #  ::= invariant (updatable) field

omitted covariant (fixed) field

¼

! Ø

New evaluation rules (Ø )

i¾½::Ò

ß Ð =Ú } Ð =Ú

i i i

i PDATE ETA

¾½::i¹½ k¾i·½::Ò

j (E-U B )

! ß Ð =Ú ¸Ð =Ú¸ Ð =Ú }

i i i i k k k

i¾½::Ò

ß  Ð =Ú }ºÐ ! Ú

i i i i i (E-RCDBETA)

204

January 15, 2000 23. POLYMORPHIC UPDATE 205

¼

Ø ! Ø j

j (E-RECORD)

i¾½::Ò i¾½::j¹½ ¼ k¾j·½::Ò

ßÐ =Ú } ! ß  Ð =Ú ¸Ð =Ø ¸  Ð =Ø }

i i i i i j k k k

j

` Ë  Ì

New type equivalence rules ( )

f½::Òg  is a permutation of

(Q-RCD-PERM)

i¾½::Ò

i¾½::Ò

` ß  Ð :Ì  Ð :Ì } }  ß

i i i i i

i

` Ë <: Ì

New subtyping rules ( )

i¾½::Ò·k i¾½::Ò

` ß  Ð :Ì } <: ß  Ð :Ì }

i i i i i

i (S-RCD-WIDTH)

i ` Ë <: Ì  = # ` Ì <: Ë

i i i i for each i if , then

(S-RCD-DEPTH)

i¾½::Ò i¾½::Ò

` ß  Ð :Ë  Ð :Ì } <: ß }

i i i i i i

` ß:::#Ð :Ë :::} <: ß:::Ð :Ë :::}

i i i

i (S-RCD-VARIANCE)

` Ø : Ì

New typing rules ( )

i ` Ø : Ì i for each i

(T-RCD)

i¾½::Ò i¾ ½::Ò

` ß  Ð =Ø } : ß  Ð :Ì }

i i i i i i

i¾½::Ò

} ` Ø : ß  Ð :Ì

i i i

(T-PROJ)

` غР: Ì

j j

` Ö : Ê ` Ê <: ß#Ð :Ì } ` Ø : Ì

j j

j (T-UPDATE)

` Ö Ð =Ø : Ê j Chapter 24

Type Operators and Kinding

The introduction to this chapter is in good shape. The technicalities are all missing at the moment.

In previous chapters, we have often made use of informal abbreviations like

ÈaiÖ Ë Ì = 8Xº ´Ë!Ì!Xµ ! X;

ÆaØ BÓÓÐ

for brevity and readability, writing ÈaiÖ , for example, instead of the

Xº ´ÆaØ!BÓÓÐ!Xµ ! X ÈaiÖ

more cumbersome 8 . What sort of thing is in itself?

Ì Ë Ì Given any pair of types Ë and , it picks out the type of “pairs of and ”—that is,

it is intuitively a function from types to types. The definition of ÈaiÖ can thus be

written explicitly as follows:

ÈaiÖ = Aº Bº 8Xº ´A!B!Xµ ! X;

Ë Ì

Formally, then, the type expression ÈaiÖ is actually a nested operator appli-

˵ Ì ÈaiÖ cation ´ÈaiÖ . In other words, itself is a function from types to type operators mapping types to types. In this chapter, we take a more careful look at the mechanisms involved in defining and using such functions.

24.1 Intuitions

Once we have introduced syntax for abstracting type expressions on type expres-

sions () and performing the corresponding instantiations (application), nothing prevents us from considering functions mapping type operators to types, func-

tions mapping type operators to type operators, etc. To keep things organized and ÈaiÖ prevent ourselves from writing nonsensical type applications like ÈaiÖ ,we

206 January 15, 2000 24. TYPE OPERATORS AND KINDING 207

classify types and type operators by kinds. E.g.,

BÓÓÐ BÓÓÐ!BÓÓÐ

¶ the kind of “proper types” like and

¶ the kind of type operators (functions from types to types)

!¶!¶

¶ the kind of functions from types to type operators

¶!¶µ!¶ ´ the kind of functions from type operators to types etc. Kinds can be thought of as the “types of types.” In essence, the system of kinds is a little copy of the simply typed lambda-calculus, placed one level higher in the hierarchy of classification. Just as in the lambda-calculus, we shall henceforth annotate the bound variables in operator abstractions with the kind of the bound

type variable, so that ÈaiÖ is really defined as:

ÈaiÖ = A::¶º B::¶º 8Xº ´A! B!Xµ ! X;

XºÌ

However, since ¶ is by far the most common case, we allow as an abbreviation

X::¶ºÌ for  . A few pictures should make all this easier to understand. The phrases of our language are divided now into three separate classes: terms, types, and kinds. The level of terms contains actual data values (integers, records, etc.) and computations (functions) over them.

Terms λx:Nat.x λX.λ x:X.x 5 ( λx:Nat.x)5 pair [Nat] [Bool] 5 false ( λx:Nat.x)true

etc.

ÆaØ!ÆaØ ÈaiÖ ÆaØ BÓÓÐ

The level of types contains proper types like ÆaØ, , and

XºX!X 8 , which classify terms,

Types

( λX.X->X)Nat Nat Pair Nat Bool Nat->Nat ∀X.X->X etc.

Terms λx:Nat.x λX.λ x:X.x 5 ( λx:Nat.x)5 pair [Nat] [Bool] 5 false ( λx:Nat.x)true etc.

January 15, 2000 24. TYPE OPERATORS AND KINDING 208

XºX!X as well as type operators like ÈaiÖ and that do not themselves classify

terms but that can be applied to type arguments to form type expressions like

XºX!XµÆaØ ´ that do classify terms. (We use the word “types” to include both proper types and type operators.)

Types λX.X->X Pair ( λX.X->X)Nat Nat Pair Nat Bool Pair Pair Nat->Nat ∀X.X->X Pair Nat etc.

Terms λx:Nat.x λX.λ x:X.x 5 ( λx:Nat.x)5 pair [Nat] [Bool] 5 false ( λx:Nat.x)true etc.

Proper types are classified by the kind ¶, pronounced “kind type” or just “type.”

µ¶ ¶µ¶µ¶ Type operators are classified by more complex kinds, such as ¶ and .

Kinds

* *->* *->*->* etc.

Types λX.X->X Pair ( λX.X->X)Nat Nat Pair Nat Bool Pair Pair Nat->Nat ∀X.X->X Pair Nat etc.

Terms λx:Nat.x λX.λ x:X.x 5 ( λx:Nat.x)5 pair [Nat] [Bool] 5 false ( λx:Nat.x)true etc.

Note that proper types (type expressions of kind ¶) can include type operators of

X::¶ºX!XµÆaØ ÈaiÖ ÆaØ BÓÓÐ

higher kinds as subphrases, as in ´ or .

XºX!X

Also, note the different roles in this diagram of the proper type 8 and

XºX!X XºÜ:XºÜ the type operator  . The former classifies terms like —it is a type January 15, 2000 24. TYPE OPERATORS AND KINDING 209 whose elements are functions from types to terms—while the latter is itself a func- tion from types to types, and does not have any terms as “elements.” A natural question to ask at this point is “Why stop at three levels of expres- sions?” That is, why couldn’t we go on to introduce functions from kinds to kinds, application at the level of kinds, etc., and add a fourth level to classify kind ex- pressions according to their functionality? In fact, why stop there? We could go on adding levels indefinitely! The answer is that we could very well do this, and such systems (without subtyping) have been studied under the heading of pure type systems [Bar92a, Bar92b, JMP94, MP93, Pol94, etc.] and used in computer science for applications such as theorem proving. For purposes of this book, though, there is no need to go beyond three levels.

24.2 Definitions

We now define a core calculus with type operators. At the term level, it includes just the variables, abstraction, and application of the simply typed lambda-calculus; the type level includes the usual arrow types and type variables, plus operator ab- straction and application. To formalize this system, we need to add three new things to the systems we have seen before. First, we need a collection of rules of kinding (or, more pedantically, type well-formedness), which specify how type expressions can be combined to yield

new type expressions. In effect, these rules constitute a copy of the simply typed

` Ì :: Ã Ì Ã lambda-calculus, “one level up.” We write for “type has kind in

context .”

Ü:ÌºØ Second, whenever a type Ì appears in a term (as in ), we must check that

Ì is well formed. This involves adding a new premise to the old T-ABS rule that

` Ì :: ¶ Ì ¶ checks . Note that must have exactly kind —i.e., it must be a proper

type—since it is being used to describe the values that Ü may range over. Third, note that, by introducing abstraction and application in types, we have

given ourselves the ability to write different “names” for the same type. For exam-

= XºX

ple, if Ád , then

ÆaØ ! BÓÓÐ

ÆaØ ! Ád BÓÓÐ

Ád ÆaØ ! Ád BÓÓÐ

Ád ÆaØ ! BÓÓÐ

Ád ´Ád ´Ád Æaصµ ! BÓÓÐ all mean the same thing, in the sense that they have the same terms as members.

January 15, 2000 24. TYPE OPERATORS AND KINDING 210

 µ Type operators and kinding !

Syntax

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø Ø application

Ú ::= (values...)

Ü:ÌºØ  abstraction value

Ì ::= (types...)

X type variable

X::úÌ

 operator abstraction Ì

Ì operator application

!Ì Ì type of functions

::= (contexts...)

; empty context Ü:Ì

; term variable binding

X ::Ã ; type variable binding

à ::= (kinds...)

¶ kind of proper types

µÃ

à kind of operators

¼

! Ø

Evaluation (Ø )

´Ü:Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

` Ë  Ì

Type equivalence ( )

` Ì :: Ã

(Q-REFL)

` Ì  Ì :: Ã

` Ì  Ë :: Ã

(Q-SYMM)

` Ë  Ì :: Ã

` Ë  Í :: Ã ` Í  Ì :: Ã

(Q-TRANS)

` Ë  Ì :: Ã

January 15, 2000 24. TYPE OPERATORS AND KINDING 211

; X::Ã ` Ì :: Ã ` Ì :: Ã

½¾ ½¾ ¾ ½½

½½ (Q-BETA)

` ´X::à ºÌ µ Ì  fX 7! Ì gÌ :: Ã

½½ ½¾ ¾ ¾ ½¾ ½¾

` Ë :: à µÃ ` Ì :: à µÃ

½ ¾ ½ ¾

; X::Ã ` Ë X  Ì X :: Ã ¾

½ (Q-EXT)

` Ë  Ì : à µÃ

½ ¾

; X::Ã ` Ë  Ì :: Ã

¾ ¾ ¾

½ (Q-TABS)

` X::à ºË  X::à ºÌ :: à µÃ

½ ¾ ½ ¾ ½ ¾

` Ë  Ì :: à µÃ ` Ë  Ì :: Ã

½ ½½ ½¾ ¾ ¾ ½½

½ (Q-APP)

` Ë Ë  Ì Ë :: Ã

½ ¾ ½ ¾ ½¾

` Ë  Ì :: ¶ ` Ë  Ì :: ¶

½ ½ ¾ ¾

(Q-ARROW)

` Ë !Ë  Ì !Ì :: ¶

½ ¾ ½ ¾

` Ì :: Ã

Kinding ( )

X::Ã ¾

(K-TVAR)

` X :: Ã

; X::Ã ` Ì :: Ã

¾ ¾

½ (K-TABS)

` X::à ºÌ :: à µÃ

½ ¾ ½ ¾

` Ì :: à µÃ ` Ì :: Ã

½½ ½¾ ¾ ½½

½ (K-TAPP)

` Ì Ì :: Ã

½ ¾ ½¾

` Ì :: ¶ ` Ì :: ¶ ¾

½ (K-ARROW)

` Ì !Ì :: ¶

½ ¾

` Ø : Ì

Typing ( )

` Ø : Ë ` Ë  Ì :: ¶

(T-EQ)

` Ø : Ì

Ü:Ì ¾

(T-VAR)

` Ü : Ì

` Ì :: ¶ ; Ü:Ì ` Ø : Ì

½ ½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾ Abbreviations

def

= X::¶ unannotated binder for X January 15, 2000 24. TYPE OPERATORS AND KINDING 212 Chapter 25

Higher-Order Polymorphism

Just a sketch. I’m not certain whether it’s productive to develop metatheory in detail for this part of the book, or whether to refer interested readers into the literature. For F-omega itself, the proofs are not all that hard or tedious, so it may be illuminating to go through at least some of them. For later systems like F-omega-sub, it becomes increasingly heavy. (One purpose of putting some of that in would probably be to give students the impression that it’s not that easy, in case they thought type systems was a trivial topic!) When type operators are added to System F, we can abstract over types of ar- bitrary kinds. This substantially increases the power of the system. In particular, higher-order universal polymorphism (i.e., abstraction over types of kinds other

than ¶) will be used in Chapter 28 to complete our model of purely functional object-oriented programming. Higher-order existential types have more practical

uses, for building abstract data types whose hidden representation type is actually ÈaiÖ an operator like Äi×Ø or .

25.1 Higher-Order Universal Types

The higher-order extension of the polymorphic lambda-calculus is formed by sim-

:Ã X ply allowing X: in place of just in the original definition of System F.

For example, here is a ridiculously polymorphic identity function

ÛaÝÈÓÐÝÁd = F::¶µ¶º Xº Ü:F Xº Ü;

Á

ÛaÝÈÓÐÝÁd : 8F::¶µ¶º 8Xº F X ! F X

and here is a typical use:

ÛaÝÈÓÐÝÁd [Yºßa:Y}] [BÓÓÐ] ßa=ØÖÙe};

213 January 15, 2000 25. HIGHER-ORDER POLYMORPHISM 214

25.1.1 Exercise: Write and typecheck a ridiculously polymorphic aÔÔÐÝÌÛice func-

F::¶µ¶º 8Xº ´´F Xµ ! ´F Xµµ ! ´F Xµ ¾ tion, of type 8 .

We will see some more interesting applications of higher-order universal types

in later chapters. !

F : Higher-order polymorphic lambda-calculus System F + µ

New syntactic forms

Ø ::= ... (terms...)

X ::à ºØ  type abstraction

Ú ::= ... (values...)

X :: à ºØ  type abstraction value

Ì ::= ... (types...)

X ::à ºÌ

8 universal type

¼

! Ø

New evaluation rules (Ø )

´X ::à ºØ µ [Ì ] ! fX 7! Ì gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA2)

` Ë  Ì

New type equivalence rules ( )

; X ::Ã ` Ë  Ì :: ¶

¾ ¾

½ (Q-ALL)

`8X ºË 8X ºÌ :: ¶

::Ã ::Ã

¾ ¾

½ ½

` Ì :: Ã

New kinding rules ( )

; X::Ã ` Ì :: ¶ ¾

½ (K-ALL)

`8X::à ºÌ :: ¶

½ ¾

` Ø : Ì

New typing rules ( )

; X ::Ã ` Ø : Ì

½ ¾ ¾

(T-TABS)

` X ::à ºØ : 8X ::à ºÌ

½ ¾ ½ ¾

` Ø : 8X ::à ºÌ ` Ì :: Ã

½ ½½ ½¾ ¾ ½½

(T-TAPP)

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾ January 15, 2000 25. HIGHER-ORDER POLYMORPHISM 215

25.2 Higher-Order Existential Types

Similarly, the higher-order variant of existential types is obtained by generalizing

X::Ã 9

X to in the original definition of .

!

9 : Higher-order existential types F < +

New syntactic forms

Ì ::= ... (types...)

9X ::à ¸Ì}

ß existential type

` Ø : Ì

New typing rules ( )

` Ø : fX 7! ÍgÌ ` ß9X::à ¸Ì } : ¶

¾ ¾ ½ ¾

(T-PACK)

` ß9X=Í¸Ø } a× ß9X ¸Ì } : ß9X ¸Ì }

::Ã ::Ã

¾ ¾ ¾

½ ½

` Ø : 9X ::à ºÌ ; X ::à ; Ü:Ì ` Ø : Ì

½ ½½ ½¾ ½½ ½¾ ¾ ¾

(T-UNPACK)

` ÐeØ ßX¸Ü}=Ø iÒ Ø : Ì

½ ¾ ¾

For example, here is an ADT (cf. Section ??) that provides the type operator

ÈaiÖ abstractly:

ÐeØ ÔaiÖADÌ =

ß9ÈaiÖ = Xº Yº 8ʺ ´X! Y!ʵ ! ʸ

ßÔaiÖ = Xº Yº Ü:Xº Ý:Yº

ʺ Ô:X!Y!ʺ Ô Ü Ý¸

f×Ø = Xº Yº Ô: ÈaiÖ X Yº

Ô [X] ´Ü:Xº Ý:Yº ܵ¸

×Òd = Xº Yº Ô: ÈaiÖ X Yº

Ô [Y] ´Ü:Xº Ý:Yº ݵ}}

a× ß9ÈaiÖ::¶µ ¶µ¶¸

ßÔaiÖ: 8Xº 8Yº X!Y!´ÈaiÖ X Yµ¸

f×Ø: 8Xº 8Yº ´ÈaiÖ X Yµ! X¸

×Òd: 8Xº 8Yº ´ÈaiÖ X Yµ! Y

}}

iÒ ÐeØ ßÈaiÖ¸ÔaiÖ}=ÔaiÖADÌ

ÔaiÖºf×Ø [ÆaØ] [BÓÓÐ] ´ÔaiÖºÔaiÖ [ÆaØ] [BÓÓÐ] 5 ØÖÙeµ;

25.2.1 Exercise [Recommended]: Write a program that defines the ÔaiÖ ADT, opens

it, and then defines a Äi×Ø ADT with the representation type

Äi×Ø = Xº 8ʺ ´X! Ê!ʵ ! Ê ! Ê;

cÓÒ× caÖ cdÖ ¾ and with operations ÒiÐ, , , and of appropriate types.

January 15, 2000 25. HIGHER-ORDER POLYMORPHISM 216 !

F : Summary System F+ µ

Syntax

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø

Ø application

X::úØ

 type abstraction [Ì] Ø type application

Ú ::= (values...)

Ü:̺Ø

 abstraction value

X :: ÃºØ  type abstraction value

Ì ::= (types...)

X type variable

Ì type of functions

X::úÌ

8 universal type

X::úÌ

 operator abstraction Ì Ì operator application

à ::= (kinds...)

¶ kind of proper types

µÃ à kind of operators

::= (contexts...)

; empty context Ü:Ì

; term variable binding

X::Ã

; type variable binding

¼

! Ø

Evaluation (Ø )

´Ü:Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

´X::à ºØ µ [Ì ] ! fX 7! Ì gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA2)

¼

Ø ! Ø ½

½ (E-TAPP)

¼

Ø [Ì ] ! Ø [Ì ]

½ ¾ ¾

½

` Ë  Ì Type equivalence ( )

January 15, 2000 25. HIGHER-ORDER POLYMORPHISM 217

` Ì :: Ã

(Q-REFL)

` Ì  Ì :: Ã

` Ì  Ë :: Ã

(Q-SYMM)

` Ë  Ì :: Ã

` Ë  Í :: Ã ` Í  Ì :: Ã

(Q-TRANS)

` Ë  Ì :: Ã

; X::Ã ` Ë  Ì :: ¶

½ ¾ ¾

(Q-ALL)

`8X::à ºË 8X::à ºÌ :: ¶

½ ¾ ½ ¾

; X::Ã ` Ì :: Ã ` Ì :: Ã

½½ ½¾ ½¾ ¾ ½½

(Q-BETA)

` ´X::à ºÌ µ Ì  fX 7! Ì gÌ :: Ã

½½ ½¾ ¾ ¾ ½¾ ½¾

` Ë :: à µÃ ` Ì :: à µÃ

½ ¾ ½ ¾

; X::Ã ` Ë X  Ì X :: Ã

½ ¾

(Q-EXT)

` Ë  Ì : à µÃ

½ ¾

; X::Ã ` Ë  Ì :: Ã

½ ¾ ¾ ¾

(Q-TABS)

` X::à ºË  X::à ºÌ :: à µÃ

½ ¾ ½ ¾ ½ ¾

` Ë  Ì :: à µÃ ` Ë  Ì :: Ã

½ ½ ½½ ½¾ ¾ ¾ ½½

(Q-APP)

` Ë Ë  Ì Ë :: Ã

½ ¾ ½ ¾ ½¾

` Ë  Ì :: ¶ ` Ë  Ì :: ¶

½ ½ ¾ ¾

(Q-ARROW)

` Ë !Ë  Ì !Ì :: ¶

½ ¾ ½ ¾

` Ì :: Ã

Kinding ( )

X::Ã ¾

(K-TVAR)

` X :: Ã

; X::Ã ` Ì :: ¶

½ ¾

(K-ALL)

`8X::à ºÌ :: ¶

½ ¾

; X::Ã ` Ì :: Ã

½ ¾ ¾

(K-TABS)

` X::à ºÌ :: à µÃ

½ ¾ ½ ¾

` Ì :: à µÃ ` Ì :: Ã

½ ½½ ½¾ ¾ ½½

(K-TAPP)

` Ì Ì :: Ã

½ ¾ ½¾

` Ì :: ¶ ` Ì :: ¶

½ ¾

(K-ARROW)

` Ì !Ì :: ¶

½ ¾

` Ø : Ì

Typing ( )

Ü:Ì ¾

(T-VAR)

` Ü : Ì

January 15, 2000 25. HIGHER-ORDER POLYMORPHISM 218

` Ì :: ¶ ; Ü:Ì ` Ø : Ì

½ ½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

; X::Ã ` Ø : Ì

½ ¾ ¾

(T-TABS)

` X::à ºØ : 8X::à ºÌ

½ ¾ ½ ¾

` Ø : 8X::à ºÌ ` Ì :: Ã

½ ½½ ½¾ ¾ ½½

(T-TAPP)

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾

` Ø : Ë ` Ë  Ì :: ¶

(T-EQ)

` Ø : Ì

25.3 Type Equivalence and Reduction

` Ë Î Ì :: Ã

25.3.1 Definition: The type reduction relation is defined just like

` Ë  Ì :: Ã  Î ¾

, replacing by and dropping the rule Q-SYMM.

` Ë  Ì :: Ã Í ` Ë Î Í :: Ã

25.3.2 Proposition: If , then there is some such that

` Ì Î Í :: Ã ¾ and .

Proof: Standard. ¾

25.4 Soundness

25.4.1 Lemma:

Ü:Ë;¡` Ì :: Ã ; ¡ ` Ì :: Ã

1. If ; , then .

Ü:Ë;¡` Ë  Ì :: Ã ; ¡ ` Ë  Ì :: Ã ¾ 2. If ; , then .

Proof: The kinding and type equivalence relations do not depend on term variable

bindings. ¾

Ü:Ë;¡ ` Ø : Ì ` × : Ë ; ¡ ` fÜ 7!

25.4.2 Lemma [Substitution]: If ; and , then

×gØ : Ì . ¾

Proof: Straightforward. (Quick check: where is Lemma 25.4.1 used?) ¾

¼ ¼

` Ø : Ì Ø ! Ø ` Ø : Ì ¾ 25.4.3 Theorem [Preservation]: If and , then .

Proof: Straightforward induction on evaluation derivations, using Lemma 25.4.2

for the T-VAR case. ¾ January 15, 2000 25. HIGHER-ORDER POLYMORPHISM 219

25.4.4 Lemma:

Ø ` Ø : Ì !Ì Ø ¾

1. If is a value and ½ , then is an abstraction.

Ø ` Ø : 8XºÌ Ø ¾

2. If is a value and ¾ , then is a type abstraction. Proof: The arguments for the two parts are similar; we show just (1). Since there

are only two forms of values, if Ø is a value and not an abstraction, then it must be

a type abstraction. Suppose (for a contradiction) that it is a type abstraction. Then

` Ø : Ì !Ì ¾ the given typing derivation for ½ must end with a use of T-TABS followed by at least one use of T-EQ. That is, it must have the following form: .

. µ

´ T-TABS

` Ø : 8XºË `8XºË  Í :: ¶

½¾ ½¾ ½ µ

´ T-EQ

` Ø : Í ½ .

.

` Ø : Í ` Í  Í :: ¶

Ò¹½ Ò¹½ Ò µ

´ T-EQ

` Ø : Í ` Í  Ì !Ì :: ¶

Ò Ò ½ ¾ µ

´ T-EQ

` Ø : Ì !Ì

½ ¾

Since type equivalence is transitive, we can collapse all of these uses of equivalence

`8XºË  Ì !Ì

½ ¾

into one and conclude that ½¾ .

Í `8XºË Î Í

By Proposition 25.3.2, there must be some type such that ½¾ and

` Ì !Ì Î Í Î ¾

½ . A quick inspection of the rules defining the relation shows that ¾

there can be no such Í.

` Ø : Ì

25.4.5 Theorem [Progress]: Suppose Ø is closed and stuck, and that . Then ¾ Ø is a value.

Proof: By induction on typing derivations. The T-VAR case cannot occur, because

Ø is closed. The T-ABS and T-TABS cases are immediate, since abstractions are val- ues. The T-EQ case follows directly from the induction hypothesis. The remaining

cases, for application and type application, are more interesting.

Ø = Ø Ø ` Ø : Ì !Ì ` Ø : Ì

¾ ½ ½½ ½¾ ¾ ½½ Case T-APP: ½

This case cannot occur. To see this, we reason by contradiction. Looking at the

Ø Ø ¾

evaluation rules, it is clear that a term of the form ½ can be stuck only if

Ø Ø

1. ½ is stuck (otherwise E-APP1 would apply to ), and

Ø Ø ¾

2. either ½ is not a value or else is stuck (otherwise E-APP2 would apply). Ø

From (1) and the induction hypothesis, we see that ½ must be a value; so by (2)

Ø Ø ½ and the induction hypothesis, ¾ must also be a value. But by Lemma 25.4.4(1),

must be an abstraction, which means that E-BETA applies to Ø, contradicting our assumption that it is stuck. January 15, 2000 25. HIGHER-ORDER POLYMORPHISM 220

Case T-TAPP:

Similar. ¾ Chapter 26

Implementing Higher-Order Systems

Algorithmic rules for F !

¼

Á

` Ì  Ì

Algorithmic reduction ( )

Á

` ´X::Ã º Ì µ Ì  fX 7! Ì gÌ

½¾ ¾ ¾ ½¾

½½ (RA-BETA)

¼ ¼ ¼

Á Á

Ì  Ì ` Ì ` Ì  Ì

¾ ½ ½

½ (RA-APP)

¼

Á

` Ì Ì  Ì

½ ¾

Á

` Ë  Ì

Algorithmic type equivalence ( )

Á

` X  X

(QA-TVAR)

¼ ¼

Á Á

` Ë  Ë ` Ë  Ì

(QA-REDUCEL)

Á

` Ë  Ì

¼ ¼

Á Á

` Ì  Ì ` Ë  Ì

(QA-REDUCER)

Á

` Ë  Ì

Á Á

` Ë  Ì ` Ë  Ì

½ ½ ¾ ¾

(QA-ARROW)

Á

` Ë !Ë  Ì !Ì

½ ¾ ½ ¾

Á

; X::Ã ` Ë  Ì

½ ¾ ¾

(QA-ALL)

Á

` 8X::à ºË 8X::à ºÌ

½ ¾ ½ ¾

Á

; X::Ã ` Ë  Ì

½ ¾ ¾

(QA-TABS)

Á

` X::à ºË  X::à ºÌ

½ ¾ ½ ¾

Á Á

` Ë  Ì ` Ë  Ì

½ ½ ¾ ¾

(QA-TAPP)

Á

` Ë Ë  Ì Ì

½ ¾ ½ ¾

221

January 15, 2000 26. IMPLEMENTING HIGHER-ORDER SYSTEMS 222

¼

Á

` Ì ¶ Ì Exposure ( ) otherwise

(XA-OTHER)

Á

` Ì ¶ Ì

¼ ¼ ¼¼

Á Á

` Ì  Ì ` Ì ¶ Ì

(XA-REDUCE)

¼¼

Á

` Ì ¶ Ì

Á

` Ø : Ì

Algorithmic typing ( )

Ü:Ì ¾

(TA-VAR)

Á

` Ü : Ì

Á Á

; Ü:Ì ` Ø : Ì ` Ì :: ¶

½ ¾ ¾ ½

(TA-ABS)

Á

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

Á Á Á Á

` Ø : Ì ` Ì ¶ ´Ì !Ì µ ` Ø : Ì ` Ì  Ì

½ ½ ½ ½½ ½¾ ¾ ¾ ¾ ½½

(TA-APP)

Á

Ø Ø : Ì `

½ ¾ ½¾

Á

; X::Ã ` Ø : Ì

½ ¾ ¾

(TA-TABS)

Á

` X::à ºØ : 8X::à ºÌ

½ ¾ ½ ¾

Á Á

` Ø : Ì ` Ì ¶ 8X::à ºÌ ` Ì :: Ã

½ ½ ½ ½ ½¾ ¾ ½

(TA-TAPP)

Á

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾

26.1 Definition: The set of well-formed contexts is defined as follows:

`;ok

` Ì :: ¶

` ok

; Ü:Ì

` ok

` ok

; X::Ã

` ok

¾

` Ø : Ì ` ` Ì :: ¶ ¾ 26.2 Proposition: If and ok, then .

Proof: ¾

` Ø : Ì 

26.3 Proposition: If , then every type annotation on a -abstraction

¶ ¾ within Ø” has kind (in the evident context).

Proof: Straightforward induction on typing derivations. ¾

26.4 Theorem [Equivalence of declaractive and algorithmic typing]: Suppose we

have ` ok. Then:

Á

` Ø : Ì ` Ø : Ì 1. If , then .

January 15, 2000 26. IMPLEMENTING HIGHER-ORDER SYSTEMS 223

Á

` Ø : Ì ` Ø : Ë ` Ë  Ì

2. If , then with . ¾

Proof: ¾

26.5 Theorem [Decidability]:

1. The context well-formedness rules are syntax-directed and total. 2. The algorithmic typing relation is total as long as the input context is well

formed. ¾

Proof: ¾ Chapter 27

Higher-Order Subtyping

Just a sketch.

Some kinding premises are omitted in the subtyping rules presented here...

! !

<: : F< : Higher-order bounded quantification F + F

Syntax

Ø ::= (terms...)

Ü variable

Ü:̺Ø

 abstraction Ø

Ø application

X <:Ì ºØ

 type abstraction [Ì] Ø type application

Ú ::= (values...)

Ü:̺Ø

 abstraction value

X <:Ì ºØ  type abstraction value

Ì ::= (types...)

X type variable

Ì type of functions

X <:Ì ºÌ 8 universal type

ÌÓÔ maximum type

X::úÌ

 operator abstraction Ì Ì operator application

::= (contexts...)

; empty context Ü:Ì ; term variable binding

224

January 15, 2000 27. HIGHER-ORDER SUBTYPING 225

X <:Ì ; type variable binding

à ::= (kinds...)

¶ kind of proper types

µÃ

à kind of operators

¼

! Ø

Evaluation (Ø )

´Ü:Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

´X <:Ì ºØ µ [Ì ] ! fX 7! Ì gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA2)

¼

Ø ! Ø ½

½ (E-TAPP)

¼

Ø [Ì ] ! Ø [Ì ]

½ ¾ ¾

½

` Ë  Ì

Type equivalence ( )

` Ì :: Ã

(Q-REFL)

` Ì  Ì :: Ã

` Ì  Ë :: Ã

(Q-SYMM)

` Ë  Ì :: Ã

` Ë  Í :: Ã ` Í  Ì :: Ã

(Q-TRANS)

` Ë  Ì :: Ã

` Ë  Ì :: ¶ ` Ë  Ì :: ¶

½ ½ ¾ ¾

(Q-ARROW)

` Ë !Ë  Ì !Ì :: ¶

½ ¾ ½ ¾

; X<:Í ` Ë  Ì :: ¶

¾ ¾

(Q-ALL)

`8X<:Í ºË 8X<:Í ºÌ :: ¶

¾ ¾

; X::Ã ` Ì :: Ã ` Ì :: Ã

½½ ½¾ ½¾ ¾ ½½

(Q-BETA)

` ´X::à ºÌ µ Ì  fX 7! Ì gÌ :: Ã

½½ ½¾ ¾ ¾ ½¾ ½¾

` Ë :: à µÃ ` Ì :: à µÃ

½ ¾ ½ ¾

; X::Ã ` Ë X  Ì X :: Ã

½ ¾

(Q-EXT)

` Ë  Ì : à µÃ

½ ¾

; X::Ã ` Ë  Ì :: Ã

½ ¾ ¾ ¾

(Q-TABS)

` X::à ºË  X::à ºÌ :: à µÃ

½ ¾ ½ ¾ ½ ¾

` Ë  Ì :: à µÃ ` Ë  Ì :: Ã

½ ½ ½½ ½¾ ¾ ¾ ½½

(Q-APP)

` Ë Ë  Ì Ë :: Ã

½ ¾ ½ ¾ ½¾

January 15, 2000 27. HIGHER-ORDER SUBTYPING 226

` Ì :: Ã

Kinding ( )

X<:Ì ¾ ` Ì :: Ã

(K-TVAR)

` X :: Ã

; X<:Ì ` Ì :: ¶

½ ¾

(K-ALL)

`8X <:Ì ºÌ :: ¶

½ ¾

; X <:ÌÓÔ ` Ì :: Ã

à ¾ ¾

½ (K-TABS)

` X::à ºÌ :: à µÃ

½ ¾ ½ ¾

` Ì :: à µÃ ` Ì :: Ã

½ ½½ ½¾ ¾ ½½

(K-TAPP)

` Ì Ì :: Ã

½ ¾ ½¾

` Ì :: ¶ ` Ì :: ¶

½ ¾

(K-ARROW)

` Ì !Ì :: ¶

½ ¾

` Ë <: Ì

Subtyping ( )

` Ë <: Í ` Í <: Ì

(S-TRANS)

` Ë <: Ì

` Ë  Ì :: Ã

(S-EQV)

` Ë <: Ì

` Ë <: ÌÓÔ

(S-TOP)

` Ì <: Ë ` Ë <: Ì

½ ½ ¾ ¾

(S-ARROW)

` Ë !Ë <: Ì !Ì

½ ¾ ½ ¾

X<:Ì ¾

(S-TVAR)

` X <: Ì

; X<:Í ` Ë <: Ì

½ ¾ ¾

(S-ALL)

`8X<:Í ºË <: 8X<:Í ºÌ

½ ¾ ½ ¾

; X::Ã ` Ë <: Ì ¾

¾ (S-ABS)

` X::ÃºË <: X::úÌ

¾ ¾

` Ë <: Ì ½

½ (S-APP)

` Ë Í <: Ì Í

½ ½

` Ø : Ì

Typing ( )

Ü:Ì ¾

(T-VAR)

` Ü : Ì

` Ì :: ¶ ; Ü:Ì ` Ø : Ì

½ ½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

January 15, 2000 27. HIGHER-ORDER SUBTYPING 227

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

` Ø : Ë ` Ë <: Ì

(T-SUB)

` Ø : Ì

; X <:Ì ` Ø : Ì

¾ ¾

(T-TABS)

` X <:Ì ºØ : 8X <:Ì ºÌ

¾ ¾

` Ø : 8X <:Ì ºÌ ` Ì <: Ì

½ ½½ ½¾ ¾ ½½

(T-TAPP)

` Ø [Ì ] : fX 7! Ì gÌ

½ ¾ ¾ ½¾ Abbreviations

def

= X <:ÌÓÔ unannotated binder for X

def

ÌÓÔ ÌÓÔ

= ¶

def

ÌÓÔ = X::Ã º ÌÓÔ

à µÃ ½ Ã

½ ¾ ¾ Chapter 28

Pure Objects and Classes

Technically complete, more or less. Work needed on writing.

28.1 Simple Objects

Recall (from Chapter 19) the type of pure (or “purely functional”) CÓÙÒØeÖ objects:

CÓÙÒØeÖ = ß9X¸ ß×ØaØe:X¸ ÑeØhÓd×:ßgeØ: X!Æaظ iÒc:X!X}}};

The representation type of counters:

CÓÙÒØeÖÊ = ßÜ:ÆaØ};

A counter object:

c = ß9X = Æaظ

ß×ØaØe = 5¸

ÑeØhÓd× = ßgeØ = Ü:Æaغ ܸ

iÒc = Ü:Æaغ ×Ùcc´Üµ}}}

a× CÓÙÒØeÖ;

Á

c : CÓÙÒØeÖ

Message-sending operations:

×eÒdgeØ = c:CÓÙÒØeÖº

ÐeØ ßX¸bÓdÝ} = c iÒ

bÓdݺÑeØhÓd׺geØ´bÓdݺ×ØaØeµ;

Á

×eÒdgeØ : CÓÙÒØeÖ ! ÆaØ

×eÒdiÒc = c:CÓÙÒØeÖº

ÐeØ ßX¸bÓdÝ} = c iÒ

ß9X = X¸

ß×ØaØe = bÓdݺÑeØhÓd׺iÒc´bÓdݺ×ØaØeµ¸

ÑeØhÓd× = bÓdݺÑeØhÓd×}}

a× CÓÙÒØeÖ;

228

January 15, 2000 28. PURE OBJECTS AND CLASSES 229

Á

×eÒdiÒc : CÓÙÒØeÖ ! CÓÙÒØeÖ

addØhÖee = c:CÓÙÒØeÖº ×eÒdiÒc ´×eÒdiÒc ´×eÒdiÒc cµµ;

Á

addØhÖee : CÓÙÒØeÖ ! CÓÙÒØeÖ

c¿ = addØhÖee c;

×eÒdgeØ c¿;

Á

c¿ : CÓÙÒØeÖ

8 : ÆaØ

28.2 Subtyping

Recall (from Section ??) the subtyping rule for existential types:

This means that if we define an object type with more methods than our CÓÙÒØeÖ

type

Êe×eØCÓÙÒØeÖ =

ß9X¸ ß×ØaØe:X¸ ÑeØhÓd×:ßgeØ: X!Æaظ iÒc:X! X¸ Öe×eØ:X! X}}};

we will have:

Êe×eØCÓÙÒØeÖ <: CÓÙÒØeÖ

So if we define a reset counter object

Öc = ß9X = Æaظ

ß×ØaØe = ¼¸

ÑeØhÓd× = ßgeØ = Ü:Æaغ ܸ

iÒc = Ü:Æaغ ×Ùcc´Üµ¸

Öe×eØ = Ü:Æaغ ¼}}}

a× Êe×eØCÓÙÒØeÖ;

Á

Öc : Êe×eØCÓÙÒØeÖ

×eÒdiÒc addØhÖee

we can pass it as a legal argument to ×eÒdgeØ and , and hence also :

Öc¿ = addØhÖee Öc;

×eÒdgeØ Öc¿;

Á

Öc¿ : CÓÙÒØeÖ

¿ : ÆaØ CÓÙÒØeÖ Notice, though, that the type of Öc¿ here is just – passing it through the

addØhÖee operation has lost some information about its type. January 15, 2000 28. PURE OBJECTS AND CLASSES 230

28.3 Interface Types

Using type operators, we rewrite the type CÓÙÒØeÖ in two parts,

CÓÙÒØeÖ = ÇbjecØ CÓÙÒØeÖÅ;

where

CÓÙÒØeÖÅ = ʺ ßgeØ: Ê!Æaظ iÒc:Ê! Ê};

Á

CÓÙÒØeÖÅ = ʺ ßgeØ:Ê! Æaظ iÒc:Ê! Ê}: ¶ µ ¶ is a type operator representing the interface of counter objects (the part that is

specific to the fact that these are counters and not some other kind of objects) and

ÇbjecØ = Á::¶µ ¶º ß9X¸ ß×ØaØe:X¸ ÑeØhÓd×:´Á Xµ}};

Á

ÇbjecØ = Á::¶µ ¶º ß9X¸ ß×ØaØe:X¸ÑeØhÓd×:Á X}}: ´¶µ ¶µ µ ¶ is a type operator (whose parameter is a type operator!) that captures the common structure of all object types.

If we similarly define

Êe×eØCÓÙÒØeÖÅ = ʺ ßgeØ: Ê!Æaظ iÒc:Ê!ʸ Öe×eØ:Ê! Ê};

Êe×eØCÓÙÒØeÖ = ÇbjecØ Êe×eØCÓÙÒØeÖÅ;

Á

Êe×eØCÓÙÒØeÖÅ = ʺ ßgeØ:Ê! Æaظ iÒc:Ê! ʸ Öe×eØ:Ê! Ê}: ¶ µ ¶

Êe×eØCÓÙÒØeÖ = ÇbjecØ Êe×eØCÓÙÒØeÖÅ: ¶

we have not only

Êe×eØCÓÙÒØeÖ <: CÓÙÒØeÖ

as before but also

Êe×eØCÓÙÒØeÖÅ <: CÓÙÒØeÖÅ by the rules above for subtyping between type operators.

28.4 Sending Messages to Objects

We can now give ×eÒdiÒc a more refined typing by abstracting over sub-operators

of CÓÙÒØeÖÅ

×eÒdiÒc =

Å<:CÓÙÒØeÖź

Ó:Çbjecشŵº

ÐeØ ßX¸ b} = Ó iÒ

´ß9X = X¸

ß×ØaØe = bºÑeØhÓd׺iÒc´bº×ØaØeµ¸

ÑeØhÓd× = bºÑeØhÓd×}}

a× Çbjecشŵµ;

January 15, 2000 28. PURE OBJECTS AND CLASSES 231

Á

×eÒdiÒc : 8Å<:CÓÙÒØeÖź ÇbjecØ Å ! ÇbjecØ Å

and send messages to counter and reset-counter objects like this (assuming ×eÒdgeØ

and ×eÒdÖe×eØ are defined analogously):

×eÒdgeØ [CÓÙÒØeÖÅ] ´×eÒdiÒc [CÓÙÒØeÖÅ] cµ;

Á

6 : ÆaØ

×eÒdgeØ [Êe×eØCÓÙÒØeÖÅ]

´×eÒdÖe×eØ [Êe×eØCÓÙÒØeÖÅ]

´×eÒdiÒc [Êe×eØCÓÙÒØeÖÅ] Öcµµ;

Á

¼ : ÆaØ

Intuitively, the type of ×eÒdiÒc can be read “give me an object interface refining the interface of counters, then give me an object with that interface, and I’ll return you another object with the same interface.”

28.4.1 Exercise: Check carefully that ×eÒdiÒc has the claimed type and that the ¾

expressions involving applications of ×eÒdiÒc are well typed.

×eÒdÖe×eØ ¾ 28.4.2 Exercise: Define ×eÒdgeØ and .

28.5 Simple Classes

In Chapter 14, we defined a class to be a function from states to objects, where objects were records of methods. Here, an object is more than just a record of methods: it includes a representation type and a state as well as methods. More- over, each of the methods here takes the state as a parameter, so it doesn’t make sense to pass the state to the class. In fact, a class here (as long as we are holding the representation type fixed) is just a record of methods – no packaging, and no

abstraction of the whole thing on the state.

CÓÙÒØeÖÊ = ÆaØ;

cÓÙÒØeÖCÐa×× =

ßgeØ = Ü:CÓÙÒØeÖʺ ܸ

iÒc = Ü:CÓÙÒØeÖʺ ×Ùcc´Üµ}

a× ßgeØ: CÓÙÒØeÖÊ! Æaظ iÒc:CÓÙÒØeÖÊ! CÓÙÒØeÖÊ};

Á

cÓÙÒØeÖCÐa×× : ßgeØ:CÓÙÒØeÖÊ! Æaظ iÒc:CÓÙÒØeÖÊ! CÓÙÒØeÖÊ}

Or, using the CÓÙÒØeÖÅ operator to write the annotation more tersely:

cÓÙÒØeÖCÐa×× =

ßgeØ = Ü:CÓÙÒØeÖʺ ܸ

iÒc = Ü:CÓÙÒØeÖʺ ×Ùcc´Üµ}

a× CÓÙÒØeÖÅ CÓÙÒØeÖÊ;

January 15, 2000 28. PURE OBJECTS AND CLASSES 232

Á

cÓÙÒØeÖCÐa×× : CÓÙÒØeÖÅ CÓÙÒØeÖÊ

We then build an instance by adding state and packaging:

c = ß9X = CÓÙÒØeÖʸ

ß×ØaØe = ¼¸

ÑeØhÓd× = cÓÙÒØeÖCÐa××}}

a× CÓÙÒØeÖ;

Á

c : CÓÙÒØeÖ

Here is a simple subclass...

Öe×eØCÓÙÒØeÖCÐa×× =

ÐeØ ×ÙÔeÖ = cÓÙÒØeÖCÐa×× iÒ

ßgeØ = ×ÙÔeÖºgeظ

iÒc = ×ÙÔeÖºiÒc¸

Öe×eØ = Ü:CÓÙÒØeÖʺ ¼}

a× Êe×eØCÓÙÒØeÖÅ CÓÙÒØeÖÊ;

Á

Öe×eØCÓÙÒØeÖCÐa×× : Êe×eØCÓÙÒØeÖÅ CÓÙÒØeÖÊ

28.6 Adding Instance Variables

A record representation for counters:

CÓÙÒØeÖÊ = ßÜ:ÆaØ};

cÓÙÒØeÖCÐa×× =

ßgeØ = ×:CÓÙÒØeÖʺ ׺ܸ

iÒc = ×:CÓÙÒØeÖʺ ßÜ=×Ùcc´×ºÜµ}}

a× CÓÙÒØeÖÅ CÓÙÒØeÖÊ;

A more interesting representation using updatable records (Chapter 23):

CÓÙÒØeÖÊ = ß#Ü:ÆaØ};

cÓÙÒØeÖCÐa×× =

ßgeØ = ×:CÓÙÒØeÖʺ ׺ܸ

iÒc = ×:CÓÙÒØeÖʺ × Ü=×Ùcc´×ºÜµ}

a× CÓÙÒØeÖÅ CÓÙÒØeÖÊ;

Á

cÓÙÒØeÖCÐa×× : CÓÙÒØeÖÅ CÓÙÒØeÖÊ

cÓÙÒØeÖCÐa×× : CÓÙÒØeÖÅ CÓÙÒØeÖÊ

(Note that objects built from these classes will have the same old type CÓÙÒØeÖ, and the same message-sending code as before will apply without change.) Now, because we’ve used polymorphic update operations to define the meth- ods of the counter class, it is actually not necessary to know that the state has

exactly type CÓÙÒØeÖÊ: we can also work with states that are subtypes of this type.

January 15, 2000 28. PURE OBJECTS AND CLASSES 233

cÓÙÒØeÖCÐa×× =

Ê<:CÓÙÒØeÖʺ

ßgeØ = ×:ʺ ׺ܸ

iÒc = ×:ʺ × Ü=×Ùcc´×ºÜµ}

a× CÓÙÒØeÖÅ Ê;

Á

cÓÙÒØeÖCÐa×× : 8Ê<:CÓÙÒØeÖʺ CÓÙÒØeÖÅ Ê CÓÙÒØeÖÊ To build an object from the new cÓÙÒØeÖCÐa××, we simply supply itself

as the representation:

c = ß9X = CÓÙÒØeÖʸ

ß×ØaØe = ß#Ü=¼}¸

ÑeØhÓd× = cÓÙÒØeÖCÐa×× [CÓÙÒØeÖÊ]}}

a× CÓÙÒØeÖ;

Á

c : CÓÙÒØeÖ ××

We can write Öe×eØCÓÙÒØeÖCÐa in the same style:

Öe×eØCÓÙÒØeÖCÐa×× =

Ê<:CÓÙÒØeÖʺ

ÐeØ ×ÙÔeÖ = cÓÙÒØeÖCÐa×× [Ê] iÒ

ßgeØ = ×ÙÔeÖºgeظ

iÒc = ×ÙÔeÖºiÒc¸

Öe×eØ = ×:ʺ × Ü=¼}

a× Êe×eØCÓÙÒØeÖÅ Ê;

Á

Öe×eØCÓÙÒØeÖCÐa×× : 8Ê<:CÓÙÒØeÖʺ Êe×eØCÓÙÒØeÖÅ Ê × Finally, we can write backÙÔCÓÙÒØeÖCÐa× in the same style, this time abstract-

ing over a subtype of BackÙÔCÓÙÒØeÖÊ: We can define another subclass – backup

counters – this time using a different representation type:

BackÙÔCÓÙÒØeÖÅ = ʺ ßgeØ: Ê!Æaظ iÒc:Ê! ʸ Öe×eØ:Ê! ʸ backÙÔ:Ê! Ê};

BackÙÔCÓÙÒØeÖÊ = ß#Ü:Æaظ#ÓÐd:ÆaØ};

backÙÔCÓÙÒØeÖCÐa×× =

Ê<:BackÙÔCÓÙÒØeÖʺ

ÐeØ ×ÙÔeÖ = Öe×eØCÓÙÒØeÖCÐa×× [Ê] iÒ

ßgeØ = ×ÙÔeÖºgeظ

iÒc = ×ÙÔeÖºiÒc¸

Öe×eØ = ×:ʺ × Ü=׺ÓÐd¸

backÙÔ = ×:ʺ × ÓÐd=׺Ü}

a× BackÙÔCÓÙÒØeÖÅ Ê;

Á

backÙÔCÓÙÒØeÖCÐa×× : 8Ê<:BackÙÔCÓÙÒØeÖʺ BackÙÔCÓÙÒØeÖÅ Ê

28.6.1 Exercise [Moderate]: We have used polymorphic update in this section to allow methods in classes to update “their” instance variables while leaving room for subclasses to extend the state with additional instance variables. Show that it is possible to achieve the same effect even in a type system lacking polymorphic

record update. ¾ January 15, 2000 28. PURE OBJECTS AND CLASSES 234

28.7 Classes with “Self”

In Section 14.6, we saw how to extend imperative classes with a mechanism allow- ing the methods of a class to refer to each other recursively. This extension also makes sense in the pure setting.

We begin by abstracting cÓÙÒØeÖCÐa×× on a collection of methods (appropriate

for the same representation type Ê):

cÓÙÒØeÖCÐa×× =

Ê<:CÓÙÒØeÖʺ

×eÐf: CÓÙÒØeÖŠʺ

ßgeØ = ×:ʺ ׺ܸ

iÒc = ×:ʺ × Ü=×Ùcc´×ºÜµ}

a× CÓÙÒØeÖÅ Ê;

To build an object from this class, we have to build the fixed point of the function

cÓÙÒØeÖCÐa××:

c = ß9X = CÓÙÒØeÖʸ

ß×ØaØe = ß#Ü=¼}¸

ÑeØhÓd× = fiÜ ´cÓÙÒØeÖCÐa×× [CÓÙÒØeÖÊ]µ}}

a× CÓÙÒØeÖ;

Á

c : CÓÙÒØeÖ

To use this new mechanism, we define a new form of “counters with a ×eØ opera-

tion”:

ËeØCÓÙÒØeÖÅ = ʺ ßgeØ: Ê!Æaظ ×eØ:Ê! ÆaØ! ʸ iÒc:Ê! Ê}; ×eØ

The implementation of the ×eØCÓÙÒØeÖCÐa×× defines a method and uses the

geØ ×eÐf iÒc

×eØ and methods of to implement the method:

×eØCÓÙÒØeÖCÐa×× =

Ê<:CÓÙÒØeÖʺ

×eÐf: ËeØCÓÙÒØeÖŠʺ

ÐeØ ×ÙÔeÖ = cÓÙÒØeÖCÐa×× [Ê] ×eÐf iÒ

ßgeØ = ×ÙÔeÖºgeظ

×eØ = ×:ʺ Ò:Æaغ × Ü=Ò¸

iÒc = ×:ʺ ×eÐfº×eØ × ´×Ùcc´×eÐfºgeØ ×µµ}

a× ËeØCÓÙÒØeÖÅ Ê;

Finally, we can further extend ×eØCÓÙÒØeÖCÐa×× to form a class of instrumented

counters, whose ×eØ operation counts the number of times that it has been called:

ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖÅ =

ʺ ßgeØ: Ê!Æaظ ×eØ:Ê! ÆaØ! ʸ iÒc:Ê! ʸ acce××e×:Ê! ÆaØ};

ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖÊ = ß#Ü:Æaظ#cÓÙÒØ:ÆaØ};

iÒ×ØÖÙÑeÒØedCÓÙÒØeÖCÐa×× =

January 15, 2000 28. PURE OBJECTS AND CLASSES 235

Ê<:ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖʺ

×eÐf: ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖŠʺ

ÐeØ ×ÙÔeÖ = ×eØCÓÙÒØeÖCÐa×× [Ê] ×eÐf iÒ

ßgeØ = ×ÙÔeÖºgeظ

×eØ = ×:ʺ Ò:Æaغ

ÐeØ Ö = ×ÙÔeÖº×eØ × Ò iÒ

Ö cÓÙÒØ=×Ùcc´ÖºcÓÙÒص¸

iÒc = ×ÙÔeÖºiÒc¸

acce××e× = ×:ʺ ׺cÓÙÒØ}

a× ÁÒ×ØÖÙÑeÒØedCÓÙÒØeÖÅ Ê; iÒc Note that calls to iÒc are included in the access count, since is implemented in

terms of ×eÐfº×eØ.

28.8 Class Types

We can write the type of cÓÙÒØeÖCÐa×× as

CÓÙÒØeÖCÐa×× = CÐa×× CÓÙÒØeÖÅ CÓÙÒØeÖÊ;

where:

CÐa×× = Å::¶µ¶º ʺ 8Ê<:ʺ Å Ê ! Å Ê;

Á

CÐa×× = Å::¶µ¶º ʺ 8ʳ<:ʺ Šʳ ! Šʳ: ´¶µ¶µ µ ¶ µ ¶

Å Ê Ê

In other words, CÐa×× is the type of classes with representation type and ÇbjecØ methods Å. Class itself is a higher-order operator, like .

28.9 Generic Inheritance

Going further along the same lines, we can actually use type operators to con- struct well-typed terms that perform instantiation of classes (object creation) and subclassing.

The code that performs the instantiation of cÓÙÒØeÖCÐa×× to yield a counter does not depend in any way on the fact that we are building a counter as opposed

to some other kind of object. We can avoid writing this boilerplate it over and

CÓÙÒØeÖÅ CÓÙÒØeÖÊ over by abstracting out cÓÙÒØeÖCÐa××, , , and the initial value

ß#Ü=¼} as follows:

ÒeÛ =

Å<:ÌÓÔź

Ê<:ÌÓÔº

c: CÐa×× Å Êº

Ö:ʺ

ß9X = ʸ

ß×ØaØe = Ö¸

ÑeØhÓd× = fiÜ ´c [Ê]µ}}

a× ÇbjecØ Å;

January 15, 2000 28. PURE OBJECTS AND CLASSES 236

Á

ÒeÛ : 8Å<:ÌÓÔź 8ʺ CÐa×× Å Ê ! Ê ! ÇbjecØ Å

XºÌÓÔ

where we write ÌÓÔÅ for the “maximal interface” :

ÌÓÔÅ = XºÌÓÔ; cÓÙÒØeÖCÐa××

We can now build counter objects by applying ÒeÛ to as follows:

c = ÒeÛ [CÓÙÒØeÖÅ] [CÓÙÒØeÖÊ] cÓÙÒØeÖCÐa×× ß#Ü=¼};

Á

c : ÇbjecØ CÓÙÒØeÖÅ

Similarly, we can write a generic function that builds a subclass given a class and a “delta” that shows how the methods of the subclass are derived from the

methods of the superclass. We begin with the concrete subclass ×eØCÓÙÒØeÖCÐa××

from Section 28.6:

×eØCÓÙÒØeÖCÐa×× =

Ê<:CÓÙÒØeÖʺ

×eÐf: ËeØCÓÙÒØeÖŠʺ

ÐeØ ×ÙÔeÖ = cÓÙÒØeÖCÐa×× [Ê] ×eÐf iÒ

ßgeØ = ×ÙÔeÖºgeظ

×eØ = ×:ʺ Ò:Æaغ × Ü=Ò¸

iÒc = ×:ʺ ×eÐfº×eØ × ´×Ùcc´×eÐfºgeØ ×µµ}

a× ËeØCÓÙÒØeÖÅ Ê;

Abstracting out the parts that are specific to counters leaves the following param-

eterized skeleton:

eÜØeÒd =

ËÙÔeÖÅ <: ÌÓÔź

ËÙÔeÖʺ

×ÙÔeÖCÐa××: CÐa×× ËÙÔeÖÅ ËÙÔeÖʺ

ËeÐfÅ <: ËÙÔeÖź

ËeÐfÊ <: ËÙÔeÖʺ

deÐØa: ´8Ê<:ËeÐfʺ ËÙÔeÖÅ Ê ! ËeÐfÅ Ê ! ËeÐfŠʵº

´Ê<:ËeÐfʺ

×eÐf: ËeÐfŠʺ

ÐeØ ×ÙÔeÖ = ×ÙÔeÖCÐa×× [Ê] ×eÐf iÒ

deÐØa [Ê] ×ÙÔeÖ ×eÐfµ

a× CÐa×× ËeÐfÅ ËeÐfÊ;

Á

eÜØeÒd : 8ËÙÔeÖÅ<:ÌÓÔź

8ËÙÔeÖʺ

CÐa×× ËÙÔeÖÅ ËÙÔeÖÊ !

´8ËeÐfÅ<:ËÙÔeÖź

8ËeÐfÊ<:ËÙÔeÖʺ

´8Ê<:ËeÐfʺ ËÙÔeÖÅ Ê!ËeÐfÅ Ê!ËeÐfŠʵ !

CÐa×× ËeÐfÅ ËeÐfʵ

January 15, 2000 28. PURE OBJECTS AND CLASSES 237

ËÙÔeÖÅ deÐØa In other words, eÜØeÒd takes several parameters ( to ) and returns a

class—i.e., a function that takes a representation type Ê (the “final type” that will

eventually be provided by the ÒeÛ function) and a vector of “self methods” special-

ized to the type Ê and returns a new vector of self methods. The most important

bit of this definition—the bit that does all the work—is the parameter deÐØa.It

takes the final type Ê and two method vectors—the “super methods” calculated ×eÐf by instantiating the superclass at Ê and and the “self methods” provided by

ÒeÛ—and returns the self methods. cÓÙÒØeÖCÐa××

Now we can recover ×eØCÓÙÒØeÖCÐa×× by extending like this:

×eØCÓÙÒØeÖCÐa×× =

eÜØeÒd [CÓÙÒØeÖÅ] [CÓÙÒØeÖÊ] cÓÙÒØeÖCÐa××

[ËeØCÓÙÒØeÖÅ] [CÓÙÒØeÖÊ]

´Ê<:CÓÙÒØeÖʺ

×ÙÔeÖ: CÓÙÒØeÖŠʺ

×eÐf: ËeØCÓÙÒØeÖŠʺ

ßgeØ = ×ÙÔeÖºgeظ

×eØ = ×:ʺ Ò:Æaغ × Ü=Ò¸

iÒc = ×:ʺ ×eÐfº×eØ × ´×Ùcc´×eÐfºgeØ ×µµ}µ;

Á

×eØCÓÙÒØeÖCÐa×× : CÐa×× ËeØCÓÙÒØeÖÅ CÓÙÒØeÖÊ

28.9.1 Exercise [Recommended]: Use the fÙÐÐÙÔdaØe checker from the course di-

rectory to implement the following extensions to the classes above:

iÒ×ØÖÙÑeÒØedCÓÙÒØeÖCÐa×× 1. Reimplement ×eØCÓÙÒØeÖCÐa×× and using the

generic inheritance operations explored in this section.

ØeÖCÐa××

2. Extend your modified iÒ×ØÖÙÑeÒØedCÓÙÒ with a subclass that adds ¾ a Öe×eØ method. Chapter 29

Structures and Modules By Robert Harper and Benjamin Pierce

It’s not clear yet whether this sketch will eventually be just a chapter of the present book or a whole book in its own right. The latter seems more likely at the moment.

29.1 Basic Structures

X Ë Structures !

Syntax

Ø ::= (terms...)

a× Ì Ø coercion

Ü variable

Ü:̺Ø

 abstraction Ø

Ø application

Ë X=Ì::øØ} ß structure creation

bÓdÝÓf´Øµ term component of a structure

Ú ::= (values...)

Ü:̺Ø

 abstraction value

Ë X=Ì::øÚ} ß structure value

Ì ::= (types...)

X type variable

Ì type of functions

Ë X::øÌ} ß structure type

ØÝÔeÓf´Øµ type component of a structure

::= (contexts...)

238 January 15, 2000 29. STRUCTURES AND MODULES 239

; empty context Ü:Ì

; term variable binding

X::Ã ; type variable binding

à ::= (kinds...)

¶ kind of proper types

¼

! Ø

Evaluation (Ø )

Ø a× Ì ! Ø

¾ ½

½ (E-COERCE1)

´Ü:Ì ºØ µ Ú ! fÜ 7! Ú gØ

½¾ ¾ ¾ ½¾

½½ (E-BETA)

¼

Ø ! Ø

½ ½

(E-APP1)

¼

Ø Ø ! Ø Ø

½ ¾ ¾

½

¼

Ø ! Ø

¾ ¾

(E-APP2)

¼

Ú Ø ! Ú Ø

½ ¾ ½

¾

¼

Ø ! Ø ½

½ (E-BODYOF)

¼

bÓdÝÓf´Ø µ ! bÓdÝÓf´Ø µ

½

½

X ¾= ´Ú µ

FV ¾

(E-STRUCTBETA)

bÓdÝÓf´ßË X=Ì ¸Ú }µ ! Ú

½ ¾ ¾

X ¾ ´Ø µ

FV ¾

(E-STRUCTSUBST)

ßË X=Ì ¸Ø } ! ßË X=Ì ¸fX 7! Ì gØ }

½ ¾ ½ ½ ¾

¼

X ¾= ´Ø µ Ø ! Ø ¾ FV ¾

¾ (E-STRUCT)

¼

} ßË X=Ì ¸Ø } ! ßË X=Ì ¸Ø

½ ¾ ½

¾

` Ë  Ì

Type equivalence ( )

` Ì :: Ã

(Q-REFL)

` Ì  Ì :: Ã

` Ì  Ë :: Ã

(Q-SYMM)

` Ë  Ì :: Ã

` Ë  Í :: Ã ` Í  Ì :: Ã

(Q-TRANS)

` Ë  Ì :: Ã

` Ë  Ì :: ¶ ` Ë  Ì :: ¶

½ ½ ¾ ¾

(Q-ARROW)

` Ë !Ë  Ì !Ì :: ¶

½ ¾ ½ ¾

` Ì :: Ã ` fX 7! Ì gØ : Ì

½ ½ ¾ ¾

½ (Q-STRUCTBETA)

` ØÝÔeÓf´ßË X=Ì ¸Ø }µ  Ì :: Ã

½ ¾ ½ ½

January 15, 2000 29. STRUCTURES AND MODULES 240

` Ì :: Ã

Kinding ( )

` Ì :: ¶ ` Ì :: ¶

½ ¾

(K-ARROW)

` Ì !Ì :: ¶

½ ¾

X::Ã ¾

(K-TVAR)

` X :: Ã

; X::Ã ` Ì :: ¶

½ (K-STRUCT)

` ßË X::Ã¸Ì } :: ¶

½

` Ú : ßË X::Ã¸Ì } ½

½ (K-TYPEOF)

` ØÝÔeÓf´Ú µ :: Ã

½

` Ø : Ì

Typing ( )

` Ì : ¶ ` Ø : Ì

½ ½ ½

(T-COERCE)

` Ø a× Ì : Ì

½ ½ ½

Ü:Ì ¾

(T-VAR)

` Ü : Ì

` Ø : Ë ` Ë  Ì :: ¶

(T-EQ)

` Ø : Ì

` Ì :: ¶ ; Ü:Ì ` Ø : Ì

½ ½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : Ì !Ì

½ ¾ ½ ¾

` Ø : Ì !Ì ` Ø : Ì

½ ½½ ½¾ ¾ ½½

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾

` Ì :: Ã ` fX 7! Ì gØ : fX 7! Ì gÌ ; X::Ã ` Ì :: ¶

½ ½ ¾ ½ ¾ ½ ¾

½ (T-STRUCT)

` ßË X=Ì ¸Ø } : ßË X::à ¸Ì }

½ ¾ ½ ¾

` Ú : ßË X::à ºÌ }

½ ¾

¼ (T-BODYOF)

` bÓdÝÓf´Ú µ : fX 7! ØÝÔeÓf´Ú µgÌ

¼ ¼ ¾ Abbreviations

def

= X::¶ unannotated binder for X

Important points:

¯ The calculus relies on an evaluation relation to determine under what cir-

cumstances ØÝÔeÓf´Øµ makes sense. In the presence of effects, it need not make sense.

¯ We omit a general “valuability” judgement at this point, in favor of a syntac- January 15, 2000 29. STRUCTURES AND MODULES 241

tic definition of “open values” ØÝÔeÓf ¯ always makes sense on values (or more generally, later, a valuable

expression)

bÓdÝÓf ØÝÔeÓf ¯ is restricted to values because of the substitution of .(We could go a little further and allow it for nonvalues in the non-dependent case, where the substitution doesn’t do anything.)

¯ With these restrictions, all of this should be encodable using existentials with

the ÓÔeÒ elimination form.

¯ We don’t evaluate type expressions, since they play no role in computation.

This would need to be revisited if we had any kind of type analysis (DÝÒaÑic, etc.).

¯ Structure values are binders. Dependencies are eliminated during projection

(this is easy in the binary case). ØÝÔeÓf ¯ On the face of it, there are two choices for type equivalence for : (1) we can include the computation rule above for reducing a typeof applied to a structure, or (2) we can eliminate this rule and rely on reflexivity for comparing typeof(structure) expressions. We have chosen the first because it supports a “phase distinction,” in the sense that type equality never depends on any notion of equality for ordinary expressions — i.e. type equality can be computed by looking only at the types. Taking the second choice is a step

on the road to structure sharing. ØÝÔeÓf ¯ We have omitted the congruence rule for type reduction for , since

the only possible arguments to ØÝÔeÓf are already values (when we extend to paths later, this needs to be revisited — note that this may be tricky, since we do not have a “full beta-equivalence” notion of equality on terms: we may need to define a simplification relation separate from evaluation)

¯ Structure values do not have principal types, for the same reason as exis- tential values did not. The fix is the same: if every structure intro form is immediately ascribed, then the term will have a principal type. January 15, 2000 29. STRUCTURES AND MODULES 242

29.2 Record Kinds and Subkinding µ Records of types ! trcd

New syntactic forms

Ì ::= ... (types...)

i¾½::Ò

ßÐ =Ì } i i record of types

̺Рprojection

à ::= ... (kinds...)

i¾½::Ò

ßÐ ::à } i

i kind of records of types

` Ë  Ì

New type equivalence rules ( )

i¾½::Ò

` Ì :: Ã i

i (Q-TRCDBETA)

i¾½::Ò

` ßÐ =Ì }ºÐ  Ì :: Ã

i i i i i

¼ i¾½::Ò

` Ì  Ì } :: ßÐ ::Ã

½ i i

½ (Q-TYPROJ)

¼

` Ì ºÐ  Ì ºÐ :: Ã

½ i i i

½

i¾½::Ò

¼

` Ì  Ì :: Ã

i i

i (Q-TRCD)

i¾ ½::Ò i¾½::Ò ¼ i¾½::Ò

} }  ßÐ =Ì } :: ßÐ ::à ` ßÐ =Ì

i i i i i

i

¼ i¾½::Ò i¾½::Ò

` Ì :: ßÐ ::à ` Ì :: ßÐ ::à } }

i i i i

i¾½::Ò

¼

` ̺Р Ì ºÐ :: Ã

i i

i (Q-TRCDEXT)

¼ i¾½::Ò

` Ì  Ì :: ßÐ ::à }

i i

i¾½::Ò

` ßÐ =Ì } :: Ã

i i

i¾½::Ò

` ßÐ =Ì } :: Ã

i

i

f½::Òg  is a permutation of

(Q-TRCD-PERM)

i¾½::Ò

i¾½::Ò

}  ßÐ =Ì } :: à ` ßÐ =Ì

i i i

i

` Ë  Ì :: Ã ` Ã <: Ã

½ ¾

½ (Q-SUB)

` Ë  Ì :: Ã ¾

New kind formation rules

i¾ ½::Ò

` Ã

i ok

(KF-TRCD)

i¾½::Ò

` ßÐ ::à } i i ok New kind equivalence rules

January 15, 2000 29. STRUCTURES AND MODULES 243

f½::Òg

 is a permutation of

i¾½::Ò

` ßÐ ::à } i

i ok

i¾½::Ò

` ßÐ ::à }

i ok

i (KEQV-TRCD-PERM)

i¾ ½::Ò

i¾½::Ò

` ßÐ ::à }  ßÐ ::à }

i i i

i

` Ì :: Ã

New kinding rules ( )

i¾½::Ò

` Ì :: Ã i

i (K-TRCD)

i¾½::Ò i¾½::Ò

` ßÐ =Ì } :: ßÐ ::à }

i i i i

i¾½::Ò

` Ì :: ßÐ ::à }

i i

¼ (K-TYPROJ)

` Ì ºÐ :: Ã

¼ j j New abbreviations

def

ߺººÃ ººº} = ߺººi::à ººº}

i i

New subkinding rules

` Ã  Ã ¾

½ (SK-EQV)

` Ã <: Ã

½ ¾

` Ã <: Ã ` Ã <: Ã

¾ ¾ ¿

½ (SK-TRANS)

` Ã <: Ã

½ ¿

i¾½::Ò·k

` ßÐ ::à } i i ok

(S-TRCD-WIDTH)

i¾½::Ò·k i¾½::Ò

` ßÐ ::à } <: ßÐ ::à }

i i i i

i¾½::Ò i¾½::Ò

` ßÐ :: } ` ßÐ ::à }

i i i

i ok ok

i¾½::Ò

` Ë <: Ì i

i (SK-TRCD-DEPTH)

i¾½::Ò i¾½::Ò

` ßÐ :: } <: ßÐ ::à }

i i i i

Notes:

¯ We include an extensionality rule for several reasons: – It’s natural. (Programmers would expect it.) – It’s needed for selfification to work. – The present algorithm relies on it (weak argument, but there it is) January 15, 2000 29. STRUCTURES AND MODULES 244

29.3 Singleton Kinds EÕ Singleton kinds !

New syntactic forms

à ::= ... (kinds...)

Eմ̵ singleton kind

` Ë  Ì

New type equivalence rules ( )

` Ë  Ì :: Ã ` Ã <: Ã

½ ¾

½ (Q-SUB)

` Ë  Ì :: Ã

¾

` Ë :: Eմ̵

(Q-SINGLETON1)

` Ë  Ì :: ¶

` Ë  Ì :: ¶

(Q-SINGLETON2)

` Ë  Ì :: Eմ˵

New kind formation rules

` Ë :: ¶

(KF-SINGLETON)

` Eմ˵ ok

New kind equivalence rules

` Ë  Ì :: ¶

(KEQV-SINGLETON)

` Eմ˵  Eմ̵

New subkinding rules

` Ã  Ã ¾

½ (SK-EQV)

` Ã <: Ã

½ ¾

` Ã <: Ã ` Ã <: Ã

¾ ¾ ¿

½ (SK-TRANS)

` Ã <: Ã

½ ¿

` Ë :: ¶

(SK-SINGLETON)

` Eմ˵ <: ¶

` Ì :: Ã

New kinding rules ( )

` Ë :: ¶

(K-SINGLETON)

` Ë :: Eմ˵ January 15, 2000 29. STRUCTURES AND MODULES 245

29.4 Dependent Function and Record Kinds µ Dependent records of types ! trcd depkind

New syntactic forms

à ::= ... (kinds...)

X::úÃ

¥ dependent kind of operators

i¾½::Ò

ßÐ º X ::à }

i i i dependent kind of records of types

New kind formation rules

` Ã ` Ã

; X::Ã

½ ¾ ok ½ ok

(KF-TARR)

` ¥X::à ºÃ ¾

½ ok

i¾½::Ò

; X ::Ã ¡¡¡X ::Ã ` Ã

½ i¹½ i¹½ i ½ ok

(KF-TRCD)

i¾½::Ò

` ßÐ º X ::à }

i i i ok

New kind equivalence rules

¼ ¼

` Ã  Ã ; X::Ã ` Ã  Ã

½ ½ ¾ ¾

½ (KEQV-TARR)

¼ ¼

` ¥X::à ºÃ  ¥X::à ºÃ

½ ¾

½ ¾

f½::Òg

 is a permutation of

i¾½::Ò

` ßÐ º X ::à }

i i

i ok

i¾½::Ò

` ßÐ º X ::à } i i ok

i (KEQV-TRCD-PERM)

i¾½::Ò

i¾½::Ò

` ßÐ º X ::à }  ßÐ º X ::à }

i i i i i

i

` Ì :: Ã

New kinding rules ( )

; X::Ã ` Ì :: Ã

½ ¾ ¾

(K-TABS)

` X::à ºÌ :: ¥X::à ºÃ

½ ¾ ½ ¾

` Ì :: ¥X::à ºÃ ` Ì :: Ã

½ ½½ ½¾ ¾ ½½

(K-TAPP)

` Ì Ì :: fX 7! Ì g Ã

½ ¾ ¾ ½¾

i¾½::Ò

; X ::Ã ¡¡¡X ::Ã ` Ì :: Ã

½ ½ i¹½ i¹½ i i

(K-TRCD)

i¾½::Ò i¾½::Ò

` ßÐ º X =Ì º X ::à } :: ßÐ }

i i i i i i

i¾½::Ò

` Ì :: ßÐ º X ::à }

¼ i i i

(K-TYPROJ)

` Ì ºÐ :: fX 7! Ì ºÐ g ¡¡¡fX 7! Ì ºÐ gÃ

¼ j ½ ¼ ½ j¹½ ¼ j¹½ j

New subkinding rules

i¾ ½::Ò·k

` ßÐ º X ::à }

i i i ok

(S-TRCD-WIDTH)

i¾½::Ò·k i¾½::Ò

} <: ßÐ } ` ßÐ º X ::à º X ::Ã

i i i i i i

January 15, 2000 29. STRUCTURES AND MODULES 246

i¾½::Ò

` ßÐ º X :: }

i i

i ok

i¾½::Ò

` ßÐ º X ::à }

i i

i ok

i¾½::Ò

; X ::Ã ¡¡¡X ::Ã ` Ë <: Ì

½ ½ i¹½ i¹½ i i

(SK-TRCD-DEPTH)

i¾½::Ò i¾½::Ò

` ßÐ º X :: º X ::à } <: ßÐ }

i i i i i i

Notes:

¯ We introduced primitive labeled record kinds because Cardelli’s encoding doesn’t work in the presence of dependencies, because it presumes the ability to reorder labels arbitrarily to match the fixed global order; but this may break dependencies between fields.

29.5 Dependent Record Expressions and Records of Types

Dependent record terms (??) ???

New syntactic forms

Ø ::= ... (terms...)

i¾½::Ò

ßÐ º Ü =Ø }

i i i dependent record

Ú ::= ... (values...)

i¾½::Ò

ßÐ º Ü =Ú }

i i

i dependent record value

¼

! Ø

New evaluation rules (Ø )

i fÜ :::Ü g \ ´Ú µ=;

i¹½ i for each ½ FV

(E-RCDBETA)

i¾½::Ò

ßÐ º Ü =Ú }ºÐ ! Ú

i i i i i

j

j¹½ j

for each , ½ FV

j

for some , j FV

¼

Ø = fÜ 7! Ú g ¡¡¡fÜ 7! Ú gØ

½ ½ i¹½ i¹½ i

i (E-RECORDSUBST)

j¾½::i¹½ k¾i·½::Ò

ßÐ º Ü =Ú ¸Ð º Ü =Ø ¸Ð º Ü =Ø } !

j j j i i i k k k

j¾½::i¹½ ¼ k¾i·½::Ò

¸Ð º Ü =Ø } ßÐ º Ü =Ú ¸Ð º Ü =Ø

i i j j j i k k k

i< j fÜ :::Ü g \ ´Ú µ=;

i¹½ i

for each , ½ FV

fÜ :::Ü g \ ´Ø µ=;

j¹½ j

½ FV

¼

Ø ! Ø j

j (E-RECORD)

i¾½::j¹½ k¾j·½::Ò

¸Ð º Ü =Ø ¸Ð } ! ßÐ º Ü =Ú º Ü =Ø

j j j k i i i k k

i¾½::j¹½ ¼ k¾j·½::Ò

ßÐ ¸Ð º Ü =Ú ¸Ð º Ü =Ø º Ü =Ø }

i k i i j j k k

j

` Ø : Ì

New typing rules ( )

i ; Ü :Ì ; :::; Ü :Ì ` Ø : Ì

½ i¹½ i¹½ i i for each ½

(T-RCD)

i¾½::Ò i¾½::Ò

` ßÐ =Ø } : ßÐ :Ì }

º Ü º Ü

i i i i

i i January 15, 2000 29. STRUCTURES AND MODULES 247

New abbreviations

def

ߺººØ ººº} = ߺººi º Ü =Ø ººº} Ü

i i i i where is fresh

29.6 Higher-Kind Singletons

Higher-order singletons ????

New syntactic forms

à ::= ... (kinds...) :õ EÉ´Ì: higher singleton kind

New kind formation rules

` Ì :: Ã

(KF-HOS)

` EÉ´Ì::õ ok

New kind equivalence rules

¼ ¼

` Ì  Ì :: Ã ` Ã  Ã

(KEQV-HOS)

¼ ¼

` EÉ´Ì::õ  EÉ´Ì ::à µ

` Ì :: ¶

(KEQV-HOS-TYPE)

` EÉ´Ì::¶µ  Eմ̵

` Ì :: Eմ͵

(KEQV-HOS-SINGLETON)

` EÉ´Ì::Eմ͵µ  Eմ̵

` Ì :: ¥X::à ºÃ ¾

½ (KEQV-HOS-TARR)

` EÉ´Ì::¥X::à ºÃ µ  ¥X::à ºEÉ´Ì X :: à µ

½ ¾ ½ ¾

i¾½::Ò

` Ì :: ßÐ º X ::à }

i i i

i¾½::Ò i¾½::Ò

` EÉ´Ì::ßÐ º X ::à }µ  ßÐ º X ::Eɴ̺Р::à µ }

i i i i i i i

(KEQV-HOS-TRCD)

` Ì :: Ã

New kinding rules ( )

` Ì :: ¥X::à ºÃ

½ ¾

¼

; X::Ã ` Ì X :: Ã ¾

½ (K-TARR-SELF)

¼

` Ì :: ¥X::à ºÃ

½ ¾

January 15, 2000 29. STRUCTURES AND MODULES 248

i¾½::Ò

` Ì :: ßÐ º X ::à }

i i i

i¾½::Ò ¼

; X ::à ¡¡¡X ::à ` ̺Р:: Ã

½ i¹½ i¹½ i i

½ (K-TRCD-SELF)

¼ i¾½::Ò

` Ì :: ßÐ º X ::à }

i i i

29.7 First-class Substructures and Functors

Dependent functions ???

New syntactic forms

Ì ::= ... (types...) Ü:̺Ì

¥ type of dependent functions

` Ë  Ì

New type equivalence rules ( )

` Ì :: Ã

(Q-REFL)

` Ì  Ì :: Ã

` Ì  Ë :: Ã

(Q-SYMM)

` Ë  Ì :: Ã

` Ë  Í :: Ã ` Í  Ì :: Ã

(Q-TRANS)

` Ë  Ì :: Ã

` Ë  Ì :: ¶ ; Ü:Ë ` Ë  Ì :: ¶

½ ½ ½ ¾ ¾

(Q-ARROW)

` ¥Ü:Ë ºË  ¥Ü:Ì ºÌ :: ¶

½ ¾ ½ ¾

` Ì :: Ã

New kinding rules ( )

` Ì :: ¶ ; Ü:Ì ` Ì :: ¶

½ ½ ¾

(K-ARROW)

¥Ü:Ì ºÌ

` :: ¶

½ ¾

` Ø : Ì

New typing rules ( )

` Ø : Ë ` Ë  Ì :: ¶

(T-EQ)

` Ø : Ì

` Ì :: ¶ ; Ü:Ì ` Ø : Ì

½ ½ ¾ ¾

(T-ABS)

` Ü:Ì ºØ : ¥Ü:Ì ºÌ

½ ¾ ½ ¾

` Ø : ¥Ü:Ì ºÌ Ü ¾= ´Ì µ ` Ø : Ì

½½ ½¾ ½½ ¾ ½½ ½ FV

(T-APP)

` Ø Ø : Ì

½ ¾ ½¾ New abbreviations

def

Ì !Ì = ¥Ü:Ì ºÌ Ü ¾= ´Ì µ

¾ ½ ¾ ¾ ½ where FV January 15, 2000 29. STRUCTURES AND MODULES 249

Dependent records ????

New syntactic forms

Ì ::= ... (types...)

i¾½::Ò

ßÐ º Ü :Ì }

i i

i type of dependent records

` Ë  Ì

New type equivalence rules ( )

` Ì :: Ã

(Q-REFL)

` Ì  Ì :: Ã

` Ì  Ë :: Ã

(Q-SYMM)

` Ë  Ì :: Ã

` Ë  Í :: Ã ` Í  Ì :: Ã

(Q-TRANS)

` Ë  Ì :: Ã

` Ë  Ì :: ¶ ` Ë  Ì :: ¶

½ ½ ¾ ¾

(Q-ARROW)

` Ë !Ë  Ì !Ì :: ¶

½ ¾ ½ ¾

i¾½::Ò

} :: ¶ ` ßÐ º Ü :Ì

i i i

i¾½::Ò

` ßÐ º Ü :Ì } :: ¶

i i

i

 ½::Òg is a permutation of f

(Q-RCD-PERM)

i¾½::Ò

i¾½::Ò

` ßÐ º Ü :Ì }  ßÐ º Ü :Ì } :: ¶

i i i i i

i

` Ø : Ì

New typing rules ( )

` Ø : Ë ` Ë  Ì :: ¶

(T-EQ)

` Ø : Ì

; Ü :Ì ¡¡¡Ü :Ì

i ` Ø : Ì

½ ½ i¹½ i¹½ i for each i

(T-RCD)

i¾½::Ò i¾½::Ò

` ßÐ =Ø } : ßÐ º Ü :Ì }

i i i i i

i¾ ½::Ò

} ` Ø : ßÐ º Ü :Ì fÜ :::Ü g \ ´Ì µ=;

i i ½ j¹½ j i FV

(T-PROJ)

` غР: Ì

j j New abbreviations

def

ߺººÌ ººº} º Ü:Ì ººº} Ü ßºººi

= i i where is fresh

Notes:

¯ These types are only apparently dependent: the elim forms apply only in the non-dependent case, in the expectation that dependencies will first be eliminated by propagation of sharing

¯ This approach depends crucially on the presence of singleton kinds, since these provide the mechanism for propagating sharing January 15, 2000 29. STRUCTURES AND MODULES 250

¯ We hold the type of earlier substructures abstract while checking the next one — i.e., we propagate forward only type information, not “identity”

¯ The “selfification” rules allow us to specialize signatures (types of modules) to propagate sharing. They are critical.

¯ Note that the T-RCD rule here does not do any substitution of earlier fields. It could, but this would constitute a violation of abstraction (besides raising the usual issues in combination with effects). This version of the rule, though, relies on the presence of singleton kinds to be very useful. For example, we

want the expression

ßÐ=ßË ÁÒظººº}¸ г=¿}

will not have the intended type

ßк Ü:ßË ¶¸ººº}¸ гº ܳ:ØÝÔeÓf´Üµ}

by a direct application of this rule. Instead, we need to use singletons to give

the term the type

ßк Ü:ßË EÕ´ÁÒص¸ººº}¸ гº ܳ:ØÝÔeÓf´Üµ}

(a subtype of the previous type), from which T-RCD does derive the intended type.

29.8 Second-Class Modules phase-separation equations

29.9 Other points to make

¯ The old argument about whether modules are strong sums. – The argument that strong sums are “not abstract” doesn’t hold water. Our structures here are not either: the abstraction comes from the com- bination of structures with ascription (or let-binding, etc.) – A better reason is that strong sums propagate sharing information by substitution, which doesn’t scale to systems with effects (the Harper/Lillibridge calculus can be described as a variant of strong sums that does this right)

¯ Applicative vs. generative functors Chapter 30

Planned Chapters

I’m not sure yet how much material will get added after this point—it depends mostly on how much time it takes to get the rest into a polished state—but here are my top priorities:

¯ Basic material on modularity. (Bob Harper and I are working together on a de- velopment that includes enough technicalities to understand module systems of the complexity of SML97’s (or OCaml’s), including both first- and second-class vari- ants. It’s a huge task, and it’s not clear yet whether we’re going to be able to finish something, or whether, if we do, it will turn out to be just a long co-authored chapter here or a short book in its own right.)

¯ Basics of dependent types. (General sums are the point where this gets hard.)

¯ Maybe some elementary material on intersection types, linear types, or the Curry- Howard isomorphism.

¯ A chapter on Moggi’s computational lambda-calculus

¯ Something on curry-howard. (In any case, make sure these are in the bibliography: gallier notes on constructive logic)

251 Appendices

252 Appendix A

Solutions to Selected Exercises

Solution to 3.2.13:

¼

Ø ! Ø

£ ¼

Ø ! Ø

£

Ø ! Ø

£ ¼ ¼ £ ¼¼

Ø ! Ø Ø ! Ø

£ ¼¼

Ø ! Ø

Solution to 3.3.2: By induction on the structure of Ø.

Case: Ø is a value

By Proposition 3.3.1, this case cannot occur.

Ø = ×Ùcc Ø

Case: ½

Looking at the evaluation rules, we find that only the rule E-SUCC could possibly

¼ ¼¼

! Ø Ø ! Ø be used to derive Ø and (all the other rules have left-hand sides

whose outermost constructor is something other than ×Ùcc). So there must be

¼ ¼¼

Ø ! Ø Ø ! Ø

½ ½

½ two subderivations with conclusions of the form ½ and .By

Ø Ø

the induction hypothesis (which applies because ½ is a subterm of ), we obtain

¼ ¼ ¼¼ ¼¼

Ø ×Ùcc Ø = Ø = ×Ùcc Ø

½ ½ ½ ½ . But then , as required.

Ø = ÔÖed Ø

Case: ½

Here there are three evaluation rules (E-PRED, E-BETANATIZ, and E-BETANATIS)

¼ ¼¼

Ø Ø that might have been used to reduct Ø to and . Notice, however, that these

rules do not overlap: if Ø matches the left-hand side of one rule, then it definitely

does not match the left-hand side of the others. (For example, if Ø matches E-PRED,

Ø ¼ ×Ùcc Ú

then ½ is definitely not a value, in particular not or .) This tells us that

¼ ¼¼

! Ø Ø ! Ø the same rule must have been used to derive Ø and . If that rule was E-PRED, then we use the induction hypothesis as in the previous case. If it was E-BETANATIZ or E-BETANATIS, then the result is immediate.

253 January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 254

Case: Other cases Similar.

Solution to 4.2.3: There are several possibilities:

×Ùcc½ = Òº ׺ Þº × ´Ò × Þµ;

×Ùcc¾ = Òº ׺ Þº Ò × ´× Þµ;

×Ùcc¿ = Òº ÔÐÙ× c Ò; ½

Solution to 4.2.6: Here’s a simple one:

eÕÙaÐ = Ѻ Òº

aÒd ´i×ÞÖÓ ´Ñ ÔÖd Òµµ

´i×ÞÖÓ ´Ò ÔÖd ѵµ;

Solution to 4.2.7: This is the solution I had in mind:

ÒiÐ = hhº Øغ ØØ;

cÓÒ× = hº غ hhº Øغ hh h ´Ø hh Øص;

head = к Ð ´hºغhµ fÐ×;

ØaiÐ = к

f×Ø ´Ð ´ܺ Ôº ÔaiÖ ´×Òd Ôµ ´cÓÒ× Ü ´×Òd Ôµµµ

´ÔaiÖ ÒiÐ Òiеµ;

i×ÒÙÐÐ = к Ð ´hºغfÐ×µ ØÖÙ;

Here is a rather different approach:

ÒiÐ = ÔaiÖ ØÖÙ ØÖÙ;

cÓÒ× = hº غ ÔaiÖ fÐ× ´ÔaiÖ h ص;

head = Þº f×Ø ´×Òd Þµ;

ØaiÐ = Þº ×Òd ´×Òd Þµ;

i×ÒÙÐÐ = f×Ø;

Solution to 4.2.8:

ff = fº к

Øe×Ø ´i×ÒÙÐРе

´ܺ c µ ´ܺ ´ÔÐÙ× ´head е ´f ´ØaiРеµµµ c ;

¼ ¼

×ÙÑÐi×Ø = fiÜÔÓiÒØ ff;

Ð = cÓÒ× c ´cÓÒ× c ´cÓÒ× c Òiеµ;

¾ ¿ 4

eÕÙaÐ ´×ÙÑÐi×Ø Ðµ c ;

9

Á

´ܺ ݺ ܵ January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 255

Solution to 5.1.13: For convenience, let’s define a little notation first. If is a

´Üµ Ü

naming context, write for the index of in , counting from the right. Write

Ò Ü Ü =

for the context that results when is removed from . For example, if

; b; c; d ´cµ=½ Ò c = a; b; d

a , then and .

¾= ´×µ

Now, the property that we want is that, if Ü FV , then

´fÜ 7! ×gص = f ´Üµ 7! ´×µg´ ´Øµµ :

ÒÜ ÒÜ removenames removenames removenames

The proof proceeds by induction on Ø, using Definitions 4.4.5 and 5.1.9, some sim- ple calculations, and some easy lemmas about removenames and the other basic

operations on terms. Convention 4.4.4 plays a crucial role in the abstraction case.

faÐ×e ØheÒ ØÖÙe eÐ×e ¼µ Solution to 6.3.8: Here’s a counterexample: the term ´if

is ill-typed, but evaluates to the well-typed term ¼.

Solution to 7.2.3: T-TRUE and T-FALSE are introduction rules. T-IF is an elimina- tion rule. Solution to 7.3.1: Because the set of type expressions is empty (there is no base

case in the syntax of types).

Ü:Ë ` Ø : Solution to 25.4.2: The proof proceeds by induction on a derivation of ;

Ì. There are cases for each of the typing rules (or, equivalently, each of the possible

forms of Ø).

= Þ

Case T-VAR: Ø

´Þµ=Ì

with Ü

There are two sub-cases to consider, depending on whether Þ is the same as or

= Ü fÜ 7! ×gÞ = × ` × : Ë

different. If Þ , then . The required result is then , which

Ü 7! ×gÞ = Þ is among the assumptions of the lemma. Otherwise, f , and the desired

result is immediate.

Ø = Ý:Ì ºØ ½

Case T-ABS: ¾

Ì = Ì !Ì

¾ ½

; Ü:Ë; Ý:Ì ` Ø : Ì

¾ ½ ½

6= Ý Ý ¾= ´×µ

First note that, by convention 4.4.4, we may assume Ü and FV . Using

; Ý:Ì ; Ü:Ë `

weakening and permutation on the given subderivation, we obtain ¾

Ø : Ì ; Ý:Ì ` fÜ 7! ×gØ : Ì `

½ ¾ ½ ½

½ . By the induction hypothesis, .ByT-ABS,

Ý:Ì º fÜ 7! ×gØ : Ì !Ì

½ ¾ ½

¾ . But this is the needed result, since, by the definition

fÜ 7! ×gØ = Ý:Ì º fÜ 7! ×gØ ½

of substitution, ½ .

Ø = Ø Ø ¾

Case T-APP: ½

; Ü:Ë ` Ø : Ì !Ì

½ ¾ ½

; Ü:Ë ` Ø : Ì

¾ ¾

Ì = Ì

¾

` fÜ 7! ×gØ : Ì !Ì ` fÜ 7! ×gØ : Ì

¾ ½ ¾ ¾

By the induction hypothesis, ½ and .By

` fÜ 7! ×gØ fÜ 7! ×gØ : Ì ` fÜ 7! ×g´Ø Ø µ : Ì

¾ ½ ¾ T-APP, ½ , i.e., .

January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 256

= ¼

Case T-TRUE,T-FALSE: Ø

Ì = BÓÓÐ

Ü 7! ×gØ = ¼ ` fÜ 7! ×gØ : Ì

Then f , and the desired result, , is immediate.

Ø = if Ø ØheÒ Ø eÐ×e Ø

¾ ¿

Case T-IF: ½

; Ü:Ë ` Ø : BÓÓÐ

½

; Ü:Ë ` Ø : Ì

¾

; Ü:Ë ` Ø : Ì ¿

The induction hypothesis yields

` fÜ 7! ×gØ : BÓÓÐ

½

` fÜ 7! ×gØ : Ì

¾

` fÜ 7! ×gØ : Ì

¿ ,

from which the result follows by T-IF. ¾

Solution to 8.4.1:

fg ÐeØ Typed record patterns ! pat (typed)

Pattern typing rules

Ü : Ì µ Ü:Ì

` (P-VAR)

i ` Ô : Ì µ ¡

i i for each i

(P-RCD)

j¾½::Ñ i¾ ½::Ò

} µ ¡ ; :::; ¡ } : ßk :Ì ` ßÐ =Ô

½ Ò j j i i

` Ø : Ì

New typing rules ( )

` Ô : Ì µ ¡

` Ø : Ì ¡ ` Ø : Ì ;

½

½ ½ ¾ ¾

(T-LET)

` ÐeØ Ô=Ø iÒ Ø : Ì

½ ¾ ¾

Solution to 17.3.9: Here are the algorithmic constraint generation rules:

´Üµ=Ì

(CT-VAR)

` Ü : Ì j fg

F F

¼

; Ü:Ë ` Ø : Ì j ´ µ C Ü 6¾

½ F F dom

(CT-ABS)

¼

C ` Ü:輯 : Ë!Ì j

F ½ F

¼¼ ¼¼¼

¼ ¼ ¼¼

` Ø : Ì j C ` Ø : Ì j C F = X;F

F ½ ½ F ½ F ¾ ¾ F ¾

(CT-APP)

¼¼¼

` Ø Ø : X j C [ C [ fÌ = Ì !Xg

F ½ ¾ F ½ ¾ ½ ¾

` ¼ : ÆaØ j fg F

F (CT-ZERO)

¼

` Ø : Ì j C

F ½ F

(CT-SUCC)

¼

` ×Ùcc Ø : ÆaØ j C [ fÌ = ÆaØg

F ½ F

January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 257

¼ ¼ ¼¼ ¼¼ ¼¼¼

` Ø : Ì j C ` Ø : Ì j C ` Ø : Ì j C

F ½ ½ F ½ F ¾ ¾ F ¾ F ¿ ¿ F ¿

¼

C = C [ C [ C [ fÌ = ÆaØ; Ì = Ì !Ì g

½ ¾ ¿ ½ ¾ ¿ ¿

(CT-ITER)

¼

¼¼¼

` iØeÖ Ì Ø Ø Ø : Ì j C

F ½ ¾ ¿ ¿ F The equivalence of the original rules and the algorithmic presentation can be stated

as follows:

¼

` Ø : Ì j Ø C F

1. (Soundness) If F and the variables mentioned in and do

¼

F ` Ø : Ì j C

ÒF

not appear in , then F .

` Ø : Ì j C F

2. (Completeness) If X , then there is some permutation of the

X ` Ø : Ì j C F names in such that ; . Both parts are proved by straightforward induction on derivations. For the appli-

cation case in part 1, the following lemma is useful:

Ø F

If the type variables mentioned in and do not appear in and if

¼

C ` Ø : Ì j Ì C F

F , then the type variables mentioned in and do not

¼

Ò F appear in F .

For the same case in part 2, the following lemma is used:

¼ ¼

` Ø : Ì j ` Ø : Ì j C G C

F F;G F ;G If F , then , where is any sequence of fresh variable names.

Solution to 17.3.10: Representing constraint sets as lists of pairs of types, the con- straint generation algorithm is a direct transcription of the inference rules given

above.

ÐeØ Öec ÖecÓÒ cØÜ ÒeÜØÙÚaÖ Ø =

ÑaØch Ø ÛiØh

ÌÑÎaÖ´fi¸i¸_µ !

ÐeØ ØÝË = geØØÝÔe fi cØÜ i iÒ

´ØÝ˸ ÒeÜØÙÚaÖ¸ []µ

| ÌÑAb×´fi¸ ܸ ØÝ˸ ؽµ !

ÐeØ cØܳ = addbiÒdiÒg cØÜ Ü ´ÎaÖBiÒd´ØÝ˵µ iÒ

ÐeØ ´ØÝ̽¸ÒeÜØÙÚaÖ½¸cÓÒ×ØÖ½µ = ÖecÓÒ cØܳ ÒeÜØÙÚaÖ Ø½ iÒ

´ÌÝAÖÖ´ØÝ˸ ØÝ×hifØ ØÝ̽ ´¹½µµ¸ ÒeÜØÙÚaÖ½¸ cÓÒ×ØÖ½µ

| ÌÑAÔÔ´fi¸Ø½¸Ø¾µ !

ÐeØ ´ØÝ̽¸ÒeÜØÙÚaÖ½¸cÓÒ×ØÖ½µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ Ø½ iÒ

ÐeØ ´ØÝ̾¸ÒeÜØÙÚaÖ¾¸cÓÒ×ØÖ¾µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ½ ؾ iÒ

ÐeØ ÆeÜØÍÎaÖ´ØÝX¸ÒeÜØÙÚaÖ³µ = ÒeÜØÙÚaÖ¾´µ iÒ

ÐeØ ÒeÛcÓÒ×ØÖ = [´ØÝ̽¸ÌÝAÖÖ´ØÝ̾¸ÌÝÁd´ØÝXµµµ] iÒ

´´ÌÝÁd´ØÝXµµ¸ ÒeÜØÙÚaÖ³¸ ´ÒeÛcÓÒ×ØÖ cÓÒ×ØÖ½ cÓÒ×ØÖ¾µµ

| ÌÑZeÖÓ´fiµ ! ´ÌÝÆaظ ÒeÜØÙÚaÖ¸ []µ

| ÌÑËÙcc´fi¸Ø½µ !

ÐeØ ´ØÝ̽¸ÒeÜØÙÚaÖ½¸cÓÒ×ØÖ½µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ Ø½ iÒ

´ÌÝÆaظ ÒeÜØÙÚaÖ½¸ [´ØÝ̽¸ÌÝÆaص]µ

January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 258

| ÌÑÈÖed´fi¸Ø½µ !

ÐeØ ´ØÝ̽¸ÒeÜØÙÚaÖ½¸cÓÒ×ØÖ½µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ Ø½ iÒ

´ÌÝÆaظ ÒeÜØÙÚaÖ½¸ [´ØÝ̽¸ÌÝÆaص]µ

| ÌÑÁ×ZeÖÓ´fi¸Ø½µ !

ÐeØ ´ØÝ̽¸ÒeÜØÙÚaÖ½¸cÓÒ×ØÖ½µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ Ø½ iÒ

´ÌÝBÓÓи ÒeÜØÙÚaÖ½¸ [´ØÝ̽¸ÌÝÆaص]µ

| ÌÑÌÖÙe´fiµ ! ´ÌÝBÓÓи ÒeÜØÙÚaÖ¸ []µ

| ÌÑFaÐ×e´fiµ ! ´ÌÝBÓÓи ÒeÜØÙÚaÖ¸ []µ

| ÌÑÁf´fi¸Ø½¸Ø¾¸Ø¿µ !

ÐeØ ´ØÝ̽¸ÒeÜØÙÚaÖ½¸cÓÒ×ØÖ½µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ Ø½ iÒ

ÐeØ ´ØÝ̾¸ÒeÜØÙÚaÖ¾¸cÓÒ×ØÖ¾µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ½ ؾ iÒ

ÐeØ ´ØÝÌ¿¸ÒeÜØÙÚaÖ¿¸cÓÒ×ØÖ¿µ = ÖecÓÒ cØÜ ÒeÜØÙÚaÖ¾ Ø¿ iÒ

ÐeØ ÒeÛcÓÒ×ØÖ = [´ØÝ̽¸ÌÝBÓÓе; ´ØÝ̾¸ØÝÌ¿µ] iÒ

´ØÝÌ¿¸ ÒeÜØÙÚaÖ¿¸ Äi×غcÓÒcaØ [ÒeÛcÓÒ×ØÖ; cÓÒ×ØÖ½; cÓÒ×ØÖ¾; cÓÒ×ØÖ¿]µ

Solution to 17.4.4:

fX = ÆaØ; Y = X!Xg fX 7! ÆaØ; Y 7! ÆaØ!ÆaØg

fÆaØ!ÆaØ = X!Yg fX 7! ÆaØ; Y 7! ÆaØg

fX!Y = Y!Z; Z = Í!Ïg fX 7! Í!Ï; Y 7! Í!Ï; Z 7! Í!Ïg

ÆaØ = ÆaØ!Yg

f Not unifiable

Y = ÆaØ!Yg f Not unifiable

Solution to 17.4.7: One more variant of substitution is needed in the unification

function—the application of a substitution to all the types in some constraint set:

ÐeØ ×Ùb×ØiÒcÓÒ×ØÖ ØÝX ØÝÌ cÓÒ×ØÖ =

Äi×غÑaÔ

´fÙÒ ´ØÝ˽¸ØÝ˾µ !

´×Ùb×ØiÒØÝ ØÝX ØÝÌ ØÝ˽¸ ×Ùb×ØiÒØÝ ØÝX ØÝÌ ØÝ˾µµ cÓÒ×ØÖ

Also crucial is the “occur-check” that detects circular dependencies:

ÐeØ ÓccÙÖ×iÒ ØÝX ØÝÌ =

ÐeØ Öec Ó = fÙÒcØiÓÒ

ÌÝAÖÖ´ØÝ̽¸ØÝ̾µ ! Ó ØÝ̽ || Ó ØÝ̾

| ÌÝÆaØ ! faÐ×e

| ÌÝBÓÓÐ ! faÐ×e

| ÌÝÁd´×µ ! ´×=ØÝXµ

iÒ Ó ØÝÌ

The unification function is now a direct transcription of the rules given on page 126. As usual, it takes a file position and string as extra arguments to be used in print- ing error messages when unification fails. (This pedagogical version of the unifier does not work very hard to print useful error messages. In practice, “explaining” type errors can be one of the hardest parts of engineering a production compiler for a language with type reconstruction.)

January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 259

ÐeØ ÙÒifÝ fi cØÜ Ñ×g cÓÒ×ØÖ =

ÐeØ Öec Ù cÓÒ×ØÖ =

ÑaØch cÓÒ×ØÖ ÛiØh

[] !

[]

| ´ØÝ˸ÌÝÁd´ØÝXµµ :: Öe×Ø !

if ØÝË = ÌÝÁd´ØÝXµ ØheÒ

Ù Öe×Ø

eÐ×e if ÓccÙÖ×iÒ ØÝX ØÝË ØheÒ

eÖÖÓÖ fi ´Ñ×g ^ ": ciÖcÙÐaÖ cÓÒ×ØÖaiÒØ×"µ

eÐ×e

Äi×غaÔÔeÒd ´Ù ´×Ùb×ØiÒcÓÒ×ØÖ ØÝX ØÝË Öe×صµ [´ÌÝÁd´ØÝXµ¸ØÝ˵]

| ´ÌÝÁd´ØÝXµ¸ØÝ̵ :: Öe×Ø !

if ØÝÌ = ÌÝÁd´ØÝXµ ØheÒ

Ù Öe×Ø

eÐ×e if ÓccÙÖ×iÒ ØÝX ØÝÌ ØheÒ

eÖÖÓÖ fi ´Ñ×g ^ ": ciÖcÙÐaÖ cÓÒ×ØÖaiÒØ×"µ

eÐ×e

Äi×غaÔÔeÒd ´Ù ´×Ùb×ØiÒcÓÒ×ØÖ ØÝX ØÝÌ Öe×صµ [´ÌÝÁd´ØÝXµ¸ØÝ̵]

| ´ÌÝÆaظÌÝÆaص :: Öe×Ø !

Ù Öe×Ø

| ´ÌÝBÓÓиÌÝBÓÓе :: Öe×Ø !

Ù Öe×Ø

| ´ÌÝAÖÖ´ØÝ˽¸ØÝ˾µ¸ÌÝAÖÖ´ØÝÌ ½¸ØÝÌ ¾µµ :: Öe×Ø !

Ù ´´ØÝ˽¸ØÝ̽µ :: ´ØÝ˾¸ØÝ̾µ :: Öe×ص

| ´ØÝ˸ØÝ̵::Öe×Ø !

eÖÖÓÖ fi "ÍÒ×ÓÐÚabÐe cÓÒ×ØÖaiÒØ×"

Ù cÓÒ×ØÖ

Solution to 17.5.6: Extending the type reconstruction algorithm to handle records is not straightforward, though it can be done. The main difficulty is that it is not clear what constraints should be generated for a record projection. A naive first

attempt would be

` Ø : Ì j C

X

` غР: X j C [ fÌ = ß Ð :X }g

i i

X[fXg Ð

but this is not satisfactory, since this rule says, in effect, that the field i can only Ð be projected from a record containing just the field i and no others. An elegant solution was proposed by Wand [Wan87] and further developed by Wand [Wan88, Wan89], Remy [R´em89, R´em90], and others. We introduce a new kind of unification variable, called a row variable, ranging not over types but over “rows” of field labels and associated types. Using row variables, the constraint

generation rule for field projection can be written

` Ø : Ì j C X

(CT-PROJ)

` غР: X j C [ fÌ = ß  }; = Ð :X ¨ g

i i

X[fX;;g

January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 260

 ¨

where  and are row variables and the operator combines two rows (assuming

غРX Ø

that their fields are disjoint). That is, the term i has type if has a record type

  Ð :X  with fields , where contains the field i and some other fields . The constraints generated by this refined algorithm are more complicated than the simple sets of equations between types with unification variables of the original reconstruction algorithm, since the new constraint sets also involve the associative

and commutative operator ¨. A simple form of equational unification is needed to find solutions to such constraint sets.

Solution to 9.5: There are well-typed terms in this system that are not strongly

normalizing. For example, consider the following:

ؽ = Ö:Êef ´ÍÒiØ! ÍÒiصº

´Ö:=´Ü:ÍÒiغ ´!ֵܵ;

´!Öµ ÙÒiص;

ؾ = Öef ´Ü:ÍÒiغ ܵ; ؾ Applying ؽ to yields a (well-typed) divergent term.

Solution to 15.3.1: Lists:

Hungry functions:

f =

fiÜ

´f: ÆaØ!ÀÙÒgÖݺ

Ò:Æaغ

fÓÐd [ÀÙÒgÖÝ] fµ;

ff = fÓÐd [ÀÙÒgÖÝ] f;

Á

ÀÙÒgÖÝ = Aº ÆaØ ! A: ¶

f : ÆaØ ! ÀÙÒgÖÝ

ff : ÀÙÒgÖÝ

ff½ = ´ÙÒfÓÐd [ÀÙÒgÖÝ] ffµ ¼;

Á

ff½ : ÀÙÒgÖÝ

ff¾ = ´ÙÒfÓÐd [ÀÙÒgÖÝ] ff½µ ¾;

Á

ff¾ : ÀÙÒgÖÝ

Fixed points:

fiÜÔÓiÒØ =

Ì

f:Ì! ̺

´Ü:´AºA! ̵º f ´´ÙÒfÓÐd [AºA!Ì] ܵ ܵµ

´fÓÐd [AºA! Ì] ´Ü:´AºA! ̵º f ´´ÙÒfÓÐd [AºA!Ì] ܵ ܵµµ;

diÚeÖge = Xº fiÜÔÓiÒØ ´Ü:̺ ܵ;

Ì Ì

Untyped lambda-calculus:

January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 261

D = Xº X!X;

ÐaÑ = f:D! Dº fÓÐd [D] f;

aÔ = f:Dº a:Dº ´ÙÒfÓÐd [D] fµ a;

Untyped lambda-calculus with numbers and booleans:

Objects:

Ô =

ÐeØ cÖeaØe =

fiÜ

´cÖ: ßÜ:ÆaØ}! CÓÙÒØeÖº

×: ßÜ:ÆaØ}º

fÓÐd [CÓÙÒØeÖ]

ßgeØ = ׺ܸ

iÒc = _:ÍÒiغ cÖ ßÜ=×Ùcc´×ºÜµ}}µ

cÖeaØe ßÜ=¼};

Ô½ = ´ÙÒfÓÐd [CÓÙÒØeÖ] ÔµºiÒc ÙÒiØ;

´ÙÒfÓÐd [CÓÙÒØeÖ] Ô½µºgeØ;

Á

Ì = ÆaØ: ¶

fiÜÔÓiÒØ : ´Ì!̵ ! Ì

Ì

diÚeÖge : 8Xº Ì

Ì

D = Xº X ! X: ¶

ÐaÑ : ´D! Dµ ! D

aÔ : D ! D ! D

CÓÙÒØeÖ = Ⱥ ßgeØ:Æaظ iÒc:ÍÒiØ! È}: ¶

Ô : CÓÙÒØeÖ

Ô½ : CÓÙÒØeÖ

´´ÙÒfÓÐd [CÓÙÒØeÖ] Ô½µºgeص : ÆaØ

Solution to 21.2.3: Just one additional rule is needed:

Á

` b : B ` B ¶ BÓÓÐ

Á Á

` Ø : Ì ` Ø : Ì ` Ì _ Ì = Â

½ ½ ¾ ¾ ½ ¾

(TA-COND)

Á

` if b ØheÒ Ø eÐ×e Ø : Â

½ ¾

Â Ì Ì ¾ where the final premise says that is a join of ½ and in .

Solution to 21.4.2: We begin by giving a pair of algorithms that, when presented

Ë Ì Â Å

with , , and , calculate a pair of types and , which we will claim are a join Ì

and meet, respectively, of Ë and . (The second algorithm may also fail, in which

Ì

case we claim that Ë and have no meet in .)

` Ë ^ Ì = Å Å Ë Ì

We write for “ is the meet of and in context ” and

` Ë _ Ì = Â Â Ë Ì for “ is the join of and in .” The algorithms are defined simultaneously as follows. (Note that some of the cases of the definition overlap. January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 262

Since it is technically convenient to treat meet and join as functions rather than

relations, we stipulate that the first clause that applies must be chosen.)

8

Ë ` Ë <: Ì

> if

>

>

>

Ì ` Ì <: Ë

> if

>

>

>

Â!Å Ë = Ë !Ë

> ¾

if ½

>

>

>

Ì = Ì !Ì

>

½ ¾

>

<

` Ë _ Ì = Â

½ ½

` Ë ^ Ì =

` Ë ^ Ì = Å

>

¾ ¾

>

>

>

Ë = 8X<:ÍºË 8X<:ͺŠ>

if ¾

>

>

>

Ì = 8X<:ͺÌ

>

¾

>

>

>

; X<:Í ` Ë ^ Ì = Å

>

¾ ¾ >

: fail otherwise

8

Ì ` Ë <: Ì

> if

>

>

>

Ë ` Ì <: Ë

> if

>

>

>

Â Ë = X X<:Í ¾ ` Í _ Ì = Â

> if with and

>

>

>

Ì = X X<:Í ¾ ` Ë _ Í = Â Â

> if with and

>

>

>

Å!Â Ë = Ë !Ë

> ¾

if ½

>

<

Ì = Ì !Ì

½ ¾

` Ë _ Ì =

` Ë ^ Ì = Å

>

½ ½

>

>

>

` Ë _ Ì = Â

>

¾ ¾

>

>

>

8X<:ÍºÂ Ë = 8X<:ÍºË >

if ¾

>

>

>

Ì = 8X<:ͺÌ

>

¾

>

>

>

; X<:Í ` Ë _ Ì = Â

>

¾ ¾

> :

ÌÓÔ otherwise

_ Ë Ì

It is easy to check that ^ and are total functions: for every , , and , there are

 ` Ë ^ Ì = Å ` Ë _ Ì = Â

unique types Å and such that and : just note that the

Ì total weight of Ë and with respect to is always reduced in recursive calls. Now let us verify that these definitions do indeed calculate meets and joins in

the subtype relation. The argument into two parts: Proposition A.1 shows that Ì the calculated meet is a lower bound of Ë and and the join is an upper bound;

Proposition A.2 then shows that the calculated meet is greater than every common Ì lower bound of Ë and and the join is less than every common upper bound.

A.1 Proposition:

` Ë ^ Ì = Å ` Å <: Ë ` Å <: Ì

1. If , then and .

` Ë _ Ì = Â ` Ë <: Â ` Ì <: Â ¾

2. If , then and .

` Ë ^ Ì =

Proof: By a straightforward induction on the size of a “derivation” of

` Ë _ Ì = Â ^ _

Å or (i.e., the number of recursive calls to the definitions of and

 ¾ needed to calculate Å or ). January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 263

A.2 Proposition:

` Ë ^ Ì = Å Ä ` Ä <: Ë ` Ä <: Ì

1. Suppose that and, for some , that and .

` Ä <: Å

Then .

` Ë _ Ì = Â Í ` Ë <: Í ` Ì <: Í

2. Suppose that and, for some , that and .

` Â <: Í ¾

Then .

` Ä <: Ë

Proof: Simultaneously, by induction on the total size of derivations of

` Ä <: Ì ` Ë <: Í ` Ì <: Í

and (for part 1) or and (for part 2).

` Ë <: Ì ` Ì <: Ë

In both parts, let us deal first with the case where or .

` Ë <: Ì ` Ë ^ Ì = Ë ` Ë _ Ì = Ì ` Ä <: Å

If , then and . But then and

` Â <: Í ` Ì <: Ë

by assumption. Similarly when .

` Ë 6 <:Ì ` Ì 6 <:Ë To complete the proofs, assume that and and consider the two parts of the proposition in turn.

1. Consider the form of Ä.

= ÌÓÔ

Case: Ä

= ÌÓÔ Ì = ÌÓÔ ` Ë <: Ì Then Ë and ,so and this case has already been dealt

with.

= X

Case: Ä

Ì X ` Ë <: Ì ` Ì <: Ë If either Ë or is the variable , then we have either or ;

these cases have already been dealt with.

` Í <: Ë ` Í <: Ì

Otherwise, by the inversion lemma, we have and ,

¾ ` Í <: Å

where X<:Í . The induction hypothesis yields , from which

` X <: Å

follows by S-TVAR and S-TRANS.

= A!B

Case: Ä

` Ë 6 <:Ì ` Ì 6 <:Ë Ë Ì ÌÓÔ First note that, since and , neither nor can be ,so

the only remaining case is where

Ë = Î!È

Ì = Ï!É

with

` Î <: A

` B <: È

` Ï <: A

` B <: É:

= Â!Æ

Also, by the definition of meets, Å with

` Î _ Ï = Â

` È ^ É = Æ: January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 264

Applying the induction hypothesis, we obtain

` Â <: A

` B <: Æ;

` Ä <: Å

from which follows by S-ARROW.

= 8X<:ͺB Case: Ä Similar.

2. First, observe that, by the inversion lemma, there are two possibilities for Ë—

either it is a variable whose upper bound is a subtype of Í, or else its form Ì

depends on the form of Í—and similarly for . Let us deal first with the first Ì possibility for both Ë and , leaving the structural cases to be considered in

detail.

= Y ´Yµ=Ê ` Ê <: Í _

If Ë with and , then, by the definition of , we have

` Ê _ Ì = Â ` Â <: Í

. The induction hypothesis now yields , and we are Í

finished. Similarly if Ì is a variable bounded by .

Ì Í

Now suppose that the forms of Ë and depend on the form of .

= ÌÓÔ Case: Í

Immediate.

= X

Case: Í

= X Ì = X By the inversion lemma, we have Ë and ; we have dealt with this

case already.

= A!B Case: Í

Then by the inversion lemma we have

Ë = Î!È

Ì = Ï!É

with

` A <: Î

` È <: B

` A <: Ï

` É <: B:

The rest of the argument proceeds as in the corresponding case in part 1.

= 8X<:AºB Case: Í

Similar. ¾ January 15, 2000 A. SOLUTIONS TO SELECTED EXERCISES 265

Solution to 21.4.3: Ì

1. Using the inversion lemma, I count 9 common subtypes of Ë and :

¼ ¼

8X<:A !Bº A!B

¼ ¼

8X<:A !Bº ÌÓÔ!B

¼

8X<:A !Bº X

¼ ¼

8X<:A !ÌÓÔº A!B

¼ ¼

8X<:A !ÌÓÔº ÌÓÔ!B

¼

8X<:A !ÌÓÔº X

¼

8X<:ÌÓÔº A!B

¼

8X<:ÌÓÔº ÌÓÔ!B

8X<:ÌÓÔº X:

2. Both

¼ ¼

8X<:A !Bº A!B

and

¼

8X<:A !Bº X Ì

are lower bounds for Ë and , but these two types have no common supertype Ì

that is also a subtype of Ë and .

¼ ¼ ¼

!ÌÓÔ Ì!ÌÓÔ 8X<:A !Bº A!B 8X<:A !Bº X 3. Consider Ë and . (Or, if you like, and .) Solution to ??: Note that the two kinds of quantifiers—bounded and unbounded— should not be allowed to mix: there should be a subtyping rule for comparing two bounded quantifiers and another for two unbounded quantifiers, but no rule for comparing a bounded to an unbounded quantifier. Otherwise we’d be right back where we started! 1. See [KS92] for details. 2. No. In any practical language with subtyping, we will want to allow width subtyping on record types. But the empty record type is a kind of maximal type (among record types), and it can be used to cause divergence in the

subtype checker using a modified version of Ghelli’s example. If

Ì = 8[X<:ß }|] :ß a: 8[Y<:X|]:Y }

then the input

X <:ß a:Ì } ` X <: ß a: 8[X <:X |]:X }

¼ ¼ ½ ¼ ½

will cause the subtype checker to diverge. [Martin Hofmann helped work out this example.] Appendix B

Summary of Notation

B.1 Metavariable Conventions

IN TEXT IN ML CODE USAGE

Õ Ö × Ø Ù × Ø

Ô, , , , , , terms

Ý Þ Ü Ý

Ü, , , term variables

Û Ú Û

Ú, , values

Æ È É Ë Ì Í Î ØÝË ØÝÌ

Å, , , , , , , , types

B C ØÝA ØÝB

A, , , base types

¬ ­ Æ aÐÔha beØa

«, , , , unification variables

Y Z ØÝX ØÝY

X, , , type variables

Ä kà kÄ

Ã, , kinds

¡ cØÜ , contexts

fi file position information

 arbitrary typing statements

B.2 Rule Naming Conventions

PREFIX USAGE E- evaluation XA- exposure K- kinding M- matching P- pattern typing Q- type equivalence QA- algorithmic type equivalence RA- algorithmic type reduction

266 January 15, 2000 B. SUMMARY OF NOTATION 267

PREFIX USAGE S- subtyping SA- algorithmic subtyping T- typing TA- algorithmic typing Appendix C

Suggestions for Larger Projects

These need to be cleaned up, and I’d like to add several more. This appendix collects some ideas for larger course projects based on the ma- terial in these notes and on the research literature on type systems. Most of the projects involve some additional reading and some implementation work. The suggestions are roughly categorized into “T” [theoretical] projects, which are more open-ended and may require more reading, thinking, and design before getting started, and “I” [implementation] projects, which are somewhat more spe- cific and involve getting down to implementation fairly early. This does not mean that the “T” projects are better – or even harder, ultimately – than “I” projects, but the “I” projects may be easier to get started on. One note on the implementation-oriented projects. You should feel free to use any programming language you’re comfortable with for building projects in... but if your favorite language happens to be C or Pascal, I urge you to think seriously about learning and using some higher-level language with built-in garbage collec- tion and facilities for high-level symbol manipulation—for example, ML, Haskell, Scheme, 3, or even Java.1 All of these projects can be done in Pascal, C, or C++, but you’ll spend more time than you can imagine chasing pointer bugs.

C.1 Objects

1. [I] In their book, A Theory of Objects [AC96] (and in a series of earlier arti- cles [AC94b, AC94a, etc.]), Abadi and Cardelli have proposed a primitive cal- culus analogous to the lambda-calculus, but with objects (rather than func- tions) as the basic terms and message passing (rather than application) as the 1An object-oriented language like Java will probably be somewhat less convenient than a language with support for datatypes and pattern matching; if you do choose an OO language, you may want to structure your code according to the “visitor pattern” [GHJV94, FF98, etc.].

268 January 15, 2000 C. SUGGESTIONS FOR LARGER PROJECTS 269

basic mechanism for computation. They develop several type systems for their object-calculus (OC). Implement one or more of these. 2. [T] Bruce, Cardelli, and Pierce wrote a paper [BCP99] comparing four dif- ferent lambda-calculus encodings of objects—the “existential encoding” pre- sented in Chapters 28 and ??, the “recursive record” encoding mentioned in Chapter 15, and two other, hybrid, models with more refined properties. A number of different points of comparison are addressed in the paper, but different encodings of classes in the four object models are not considered. (a) Using the typechecker that we’ve used for exercises and for the exam- ples in the notes, implement the examples in [BCP99]. (b) Extend these examples to include encodings of classes and inheritance, following Chapter 28 in the case of the existential encoding and other papers (see the bibliography of [BCP99]) for the other encodings. (c) Compare and contrast. (d) If time remains, it is also interesting to compare and contrast the imper- ative variants of these four encodings—i.e., versions of the encodings

where the instance variables of objects can be mutable Êef cells.

3. [I] Chapter ?? shows how to do some simple examples of object-oriented

eÚeÖÝØhiÒg : programming in F< . Using the typechecker from the course web directory, develop a more significant object-oriented program following the same lines. (a) To get started, implement a group of collection classes (for example, using the collection classes of Smalltalk [GR83] as a model). Some hints for how to do this can be found in [PT94]. (b) Use these classes as a to implement a larger object-oriented pro- gram of your choice.

C.2 Encodings of Logics

1. [I] The Logical Framework of Harper, Honsell, and Plotkin [HHP92] is a typed lambda-calculus intended as a meta-language for defining logics and prov- ing theorems in them. (a) Implement LF (b) Use your implementation to encode a simple propositional logic and prove some small theorems. 2. [T] A generalization of the LF logic has been used as the core of Frank Pfen- ning’s logic programming language ELF [Pfe89, Pfe91, Pfe94, Pfe96]. January 15, 2000 C. SUGGESTIONS FOR LARGER PROJECTS 270

(a) Download and install the ELF system. (b) Use it to encode the syntax and typing rules of the simply typed lambda- calculus with subtyping and prove some simple theorems about the sys- tem, along the lines of [MP91].

C.3 Type Inference

1. [T] Implement a type inference system for the simply typed lambda-calculus (or ML) with subtyping. (The literature on approaches to this problem is huge. See [Pot97, Pot98], for example.) 2. [I] Row variables, proposed by Mitch Wand [Wan87, Wan88, Wan89] and sub- sequently refined by Didier Remy [R´em89, R´em90, RV97], provide an alter- native to subtyping as a foundation for object-oriented programming lan- guages, and can coexist smoothly with ML-style type inference. Implement a type system with type inference and row variables.

C.4 Other Type Systems

1. [T] Implement a lambda-calculus with intersection types [Rey88, Pie97] (or, for a bit more challenge, with both intersection and union types [Pie91b, Pie90, BDCd95, Hay91]). 2. [T] Implement a linear type system for the lambda-calculus [Wad91, Wad90, TWM95]. 3. [I] Implement a typed assembly language in the style of Morrisett and co-workers [MWCG98, MCGW98, MCG · 99]. 4. [T] A great variety of type systems for extensible records, developed by various researchers, are summarized and unified in Cardelli and Mitchell’s encyclo- pedic article, Operations on Records [CM91]. Implement a simple variant of their system. 5. [I] Effect type systems [JG91, TJ92], which track the computational effects of functions (memory reads and writes, allocation, etc.) in addition to their input-output behavior, have been used for a variety of purposes. Perhaps most surprisingly, Tofte and his co-workers have used “region inference” techniques to build an ML compiler that runs without a garbage collector [TT97, TB98]. Implement a simple effect inference algorithm. 6. [T] Harper and Lillibridge [HL94] and Leroy [Ler96] have independently proposed similar accounts of modules (in the style of ML) using the type- theoretic tools of existential types and (a limited form of) dependent types. January 15, 2000 C. SUGGESTIONS FOR LARGER PROJECTS 271

These accounts place powerful module systems like those of Standard ML [MTH90] and Objective Caml [Ler95] on a well-understood and tractable theoretical foundation. Read and implement one of these papers. 7. [I] A series of papers [ACPP91, LM91, ACPR95] have proposed adding a type

DÝÒaÑic to statically typed languages, in order to provide a smooth interface between statically typed and dynamically typed data.

(a) Add DÝÒaÑic to the implementation of the simply typed lambda-calculus, following [ACPP91]. (b) Extend this implementation to System F (or even Fomega), using ideas in [ACPR95] and your own creativity.

C.5 Sources for Additional Ideas

The research literature is full of descriptions of interesting type systems and ap- plications of type systems. The premier conference in the area is Principles of Programming Languages (POPL). Other conferences with a high density of papers on type systems include International Conference on Functional Programming (ICFP), Typed Lambda Calculi and Applications (TLCA), Theoretical Aspects of Computer Soft- ware (TACS), Logic in Computer Science (LICS), (among many others). Leafing through a recent proceedings of any of these conferences should yield several papers in- volving type systems. Pick one, read it carefully, and build a simple implementa- tion of the system it describes. Appendix D

Bluffers Guide to OCaml

The systems discussed in the text have all been implemented in the Objective CAML dialect of ML. An excellent compiler for this language is freely available from INRIA. Students who want to undertake the implementation exercises suggested in many chapters will need to pick up the basics of OCaml programming, if they are not already familiar with it. For programmers already familiar with another dialect of ML (e.g. Standard ML), the brief, but excellent, tutorial in the OCaml reference manual will do fine for this. Readers with no prior familiarity with any ML may wish to read some of Cousineau and Mauny’s textbook [CM98]. For the convenience of readers who just want to understand enough of the pro- gramming examples presented here to translate them into another programming language, this appendix summarizes the key features used. To be written. I have in mind something along the lines of the “Bluffers Guide to ML” in Baader and Nipkow’s recent book, Term Rewriting and All That. In fact, it might be possible to reprint that appendix entirely from this book, crediting the original authors and just translating, mutatis mutandi, SML to OCaml. (I have not talked to Baader and Nipkow about this.)

272 Appendix E

Running the Checkers

The systems discussed in the text have all been implemented in Objective CAML. You’ll find the programming exercises and experiments throughout the notes much more enjoyable if you use the implementations to check and execute your solu- tions.

E.1 Preparing Your Input

An input file for a checker consists of a sequence of clauses terminated by semi-

colons. Input clauses can have the following forms: Ø

Ø; typecheck (if appropriate) and evaluate term

= Ø; Ø Ü

Ü typecheck (if appropriate) and bind it to

"fiÐeÒaÑe"; fiÐeÒaÑe iÑÔÓÖØ include at this point

E.2 Ascii Equivalents

Programs in the text are typeset using some non-ascii symbols. When preparing input to the typechecker, you should use the following equivalents:

TYPESET ASCII

 ÐaÑbda

! ¹>

¼

³a a

¼

³b b

¼

³c c

¼

³d d

273 January 15, 2000 E. RUNNING THE CHECKERS 274

E.3 Running the Checker

Precompiled binaries for solaris can be found in the course web directory. From CIS machines, you should be able to run the checkers directly out of the web di-

rectory:

»ÑÒØ»×aÙлeÜØÖa»bcÔieÖce»ÔÙb» cÓÙÖ ×e×»7 ¼¼»c heck eÖ×»< chec keÖÒa Ñe>» f <Øe×غf>

ÙÒØÝÔed fÙÐÐÙÒØÝÔed

(where is the name of the checker that you want— , , <Øe×غf> ×iÑÔÐe, etc.—and is the name of your input file).

E.4 Compiling the Checkers

To modify the checker itself, you’ll need to make a local copy:

cÔ ¹Ö »ÑÒØ»×aÙлeÜØÖa»bcÔieÖce»ÔÙ b»cÓÙ Ö×e× »7¼¼ »chec keÖ× » <ÑÝdiÖ>

To recompile it from scratch, first install the Objective CAML compiler if necessary

(see the following section). Do

Ñake cÐeaÒ

to throw away all the existing object-code files, and then Ñake

to rebuild the executable file (called f) for the checker.

E.5 Objective Caml

On CIS machines, you should be able to use the Objective CAML compiler simply

by adding »ÑÒØ»×aÙлeÜØÖa»bcÔieÖce»biÒ» ×ÙÒ4 to your search path. On other machines (including most varieties of Unix workstations, Macs, and

Windows 95/98/NT PCs) you’ll need to install Objective Caml yourself. It can be

fÖ»ÐaÒg obtained from fØÔ:»»fØÔºiÒÖiaº . It’s quite easy to install. Bibliography

[AC94a] Mart´ın Abadi and Luca Cardelli. A theory of primitive objects: Second-order systems. In European Symposium on Programming (ESOP), Edinburgh, Scotland, 1994. [AC94b] Mart´ın Abadi and Luca Cardelli. A theory of primitive objects: Untyped and first-order systems. In Theoretical Aspects of Computer Software (TACS), Sendai, Japan, 1994. [AC96] Mart´ın Abadi and Luca Cardelli. A Theory of Objects. Springer-Verlag, 1996. [ACPP91] Mart´ın Abadi, Luca Cardelli, Benjamin Pierce, and Gordon Plotkin. Dynamic typing in a statically typed language. Transactions on Programming Languages and Systems, 13(2):237–268, April 1991. Preliminary version in Proceedings of the Sixteenth Annual ACM Symposium on Principles of Programming Lan- guages (Austin, TX), January, 1989. [ACPR95] Mart´ın Abadi, Luca Cardelli, Benjamin Pierce, and Didier R´emy. Dynamic typ- ing in polymorphic languages. Journal of Functional Programming, 5(1):111–130, January 1995. Preliminary version in Proceedings of the ACM SIGPLAN Work- shop on ML and its Applications, June 1992. [AJM94] Samson Abramsky, Radha Jagadeesan, and Pasquale Malacaria. Full abstrac- tion for PCF (extended abstract). In Masami Hagiya and John C. Mitchell, ed- itors, Theoretical Aspects of Computer Software. International Symposium TACS’94, number 789 in Lecture Notes in Computer Science, pages 1–15, Sendai, Japan, April 1994. Springer-Verlag. [AS85] Harold Abelson and Gerald Sussman. Structure and Interpretation of Computer Programs. The MIT Press, New York, 1985. [Bac81] John Backus. The history of Fortran I, II, and III. In Wexelblat, editor, History of Programming Languages, pages 25–45. Academic Press, 1981. [Bar84] H. P. Barendregt. The Lambda Calculus. North Holland, revised edition, 1984. [Bar90] H. P. Barendregt. Functional programming and lambda calculus. In Jan van Leeuwen, editor, Handbook of Theoretical Computer Science, Volume B, volume B, chapter 7, pages 321–364. Elsevier / MIT Press, 1990. [Bar92a] Henk Barendregt. Introduction to generalized type systems. Journal of Func- tional Programming, 1992.

275 January 15, 2000 BIBLIOGRAPHY 276

[Bar92b] Henk Barendregt. Lambda calculi with types. In Gabbay Abramsky and Maibaum, editors, Handbook of Logic in Computer Science, volume II. Oxford University Press, 1992. [BCGS91] Val Breazu-Tannen, Thierry Coquand, Carl Gunter, and Andre Scedrov. Inher- itance as implicit coercion. Information and Computation, 93:172–221, 1991. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object- Oriented Programming: Types, Semantics, and Language Design (MIT Press, 1994). [BCP99] Kim B. Bruce, Luca Cardelli, and Benjamin C. Pierce. Comparing object en- codings. Information and Computation, 1999. To appear in a special issue with papers from Theoretical Aspects of Computer Software (TACS), September, 1997. An earlier version appeared as an invited lecture in the Third International Workshop on Foundations of Object Oriented Languages (FOOL 3), July 1996. [BDCd95] Franco Barbanera, Mariangiola Dezani-Ciancaglini, and Ugo de’Liguoro. Inter- section and union types: Syntax and semantics. Information and Computation, 119(2):202–230, June 1995. [BDMN79] Graham M. Birtwistle, Ole-Johan Dahl, Bjorn Myhrhaug, and Kristen Nygaard. Simula Begin. Studentlitteratur (Lund, Sweden), Bratt Institut fuer neues Ler- nen (Goch, FRG), Chartwell-Bratt Ltd (Kent, England), 1979. [Ben95] Johan Van Benthem. Language in Action : Categories, Lambdas, and Dynamic Logic. MIT Press, 1995. [BFSS90] S. Bainbridge, P. Freyd, A. Scedrov, and P. Scott. Functorial polymorphism. Theoretical Computer Science, 70:35–64, 1990. [BL90] Kim B. Bruce and Giuseppe Longo. A modest model of records, inheritance, and bounded quantification. Information and Computation, 87:196–240, 1990. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Programming: Types, Semantics, and Language Design (MIT Press, 1994). An earlier version appeared in the proceedings of the IEEE Symposium on Logic in Computer Science, 1988. [BM92] Kim Bruce and John Mitchell. PER models of subtyping, recursive types and higher-order polymorphism. In Proceedings of the Nineteenth ACM Symposium on Principles of Programming Languages, Albequerque, NM, January 1992. [BOSW98] Gilad Bracha, Martin Odersky, David Stoutamire, and Philip Wadler. Mak- ing the future safe for the past: Adding genericity to the Java programming language. In Craig Chambers, editor, Object Oriented Programing: Systems, Lan- guages, and Applications (OOPSLA), ACM SIGPLAN Notices volume 33 number 10, pages 183–200, Vancouver, BC, October 1998. [Bru91] Kim B. Bruce. The equivalence of two semantic definitions for inheritance in object-oriented languages. In Proceedings of Mathematical Foundations of Pro- gramming Semantics, Pittsburgh, PA, March 1991. [Car84] Luca Cardelli. A semantics of multiple inheritance. In G. Kahn, D. MacQueen, and G. Plotkin, editors, Semantics of Data Types, volume 173 of Lecture Notes in Computer Science, pages 51–67. Springer-Verlag, 1984. Full version in Informa- tion and Computation 76(2/3):138–164, 1988. January 15, 2000 BIBLIOGRAPHY 277

[Car88] Luca Cardelli. Structural subtyping and the notion of power type. In Proceed- ings of the 15th ACM Symposium on Principles of Programming Languages, pages 70–79, San Diego, CA, January 1988. [Car89] Felice Cardone. Relational semantics for recursive types and bounded quan- tification. In Proceedings of the Sixteenth International Colloquium on Automata, Languages, and Programming, volume 372 of Lecture Notes in Computer Science,

pages 164–178, Stresa, Italy, July 1989. Springer-Verlag.

! : [Car90] Luca Cardelli. Notes about F < . Unpublished manuscript, October 1990. [Car91] Luca Cardelli. Typeful programming. In E. J. Neuhold and M. Paul, editors, Formal Description of Programming Concepts. Springer-Verlag, 1991. An ear- lier version appeared as DEC Systems Research Center Research Report #45, February 1989. [Car92] Luca Cardelli. Extensible records in a pure calculus of subtyping. Research report 81, DEC Systems Research Center, January 1992. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Programming: Types, Semantics, and Language Design (MIT Press, 1994). [Car96] Luca Cardelli. Type systems. In Allen B. Tucker, editor, Handbook of Computer Science and Engineering. CRC Press, 1996. [Cas97] Giuseppe Castagna. Object-Oriented Programming: A Unified Foundation. Springer-Verlag, 1997.

[CCH· 89] Peter Canning, William Cook, Walter Hill, Walter Olthoff, and John Mitchell. F-bounded quantification for object-oriented programming. In Fourth Interna- tional Conference on Functional Programming Languages and Computer Architec- ture, pages 273–280, September 1989. [CCHO89] Peter Canning, William Cook, Walt Hill, and Walter Olthoff. Interfaces for strongly-typed object-oriented programming. In Object Oriented Programing: Systems, Languages, and Applications (OOPSLA), pages 457–467, 1989.

[CDC78] M. Coppo and M. Dezani-Ciancaglini. A new type-assignment for -terms. Archiv Math. Logik, 19:139–156, 1978. [CDCS79] M. Coppo, M. Dezani-Ciancaglini, and P. Salle. Functional characterization

of some semantic equalities inside -calculus. In Hermann A. Maurer, editor, Proceedings of the 6th Colloquium on Automata, Languages and Programming, vol- ume 71 of LNCS, pages 133–146, Graz, Austria, July 1979. Springer. [CF58] H. B. Curry and R. Feys. Combinatory Logic, volume 1. North Holland, 1958. (Second edition, 1968).

[CG91] Pierre-Louis Curien and Giorgio Ghelli. Subtyping + extensionality: Conflu-

¬ F ence of -reductions in  . In T. Ito and A. R. Meyer, editors, Theoretical Aspects of Computer Software (Sendai, Japan), number 526 in Lecture Notes in Computer Science, pages 731–749. Springer-Verlag, September 1991. [CG92] Pierre-Louis Curien and Giorgio Ghelli. Coherence of subsumption: Minimum

typing and type-checking in F  . Mathematical Structures in Computer Science, 2:55–91, 1992. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Programming: Types, Semantics, and Language Design (MIT Press, 1994). January 15, 2000 BIBLIOGRAPHY 278

[CH88] Thierry Coquand and G´erard Huet. The Calculus of Constructions. Information and Computation, 76(2/3):95–120, February/March 1988. [CHC90] William R. Cook, Walter L. Hill, and Peter S. Canning. Inheritance is not sub- typing. In Seventeenth Annual ACM Symposium on Principles of Programming Languages, pages 125–135, San Francisco, CA, January 1990. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Pro- gramming: Types, Semantics, and Language Design (MIT Press, 1994). [CHO88] Peter Canning, Walt Hill, and Walter Olthoff. A kernel language for object- oriented programming. Technical Report STL-88-21, Hewlett-Packard Labs, 1988. [Chu36] Alonzo Church. An unsolvable problem of elementary number theory. Ameri- can Journal of Mathematics, 58:354–363, 1936. [Chu40] Alonzo Church. A formulation of the simple theory of types. Journal of Symbolic Logic, 5:56–68, 1940. [Chu41] Alonzo Church. The Calculi of Lambda Conversion. Princeton University Press, 1941. [CL91] Luca Cardelli and Giuseppe Longo. A semantic basis for Quest. Journal of Func- tional Programming, 1(4):417–458, October 1991. Preliminary version in ACM Conference on Lisp and Functional Programming, June 1990. Also available as DEC SRC Research Report 55, Feb. 1990. [CM91] Luca Cardelli and John Mitchell. Operations on records. Mathematical Struc- tures in Computer Science, 1:3–48, 1991. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Programming: Types, Se- mantics, and Language Design (MIT Press, 1994); available as DEC Systems Re- search Center Research Report #48, August, 1989, and in the proceedings of MFPS ’89, Springer LNCS volume 442. [CM98] Guy Cousineau and Michel Mauny. The Functional Approach to Programming. Cambridge University Press, 1998. [CMMS94] Luca Cardelli, Simone Martini, John C. Mitchell, and Andre Scedrov. An ex- tension of system F with subtyping. Information and Computation, 109(1–2):4–56, 1994. Preliminary version in TACS ’91 (Sendai, Japan, pp. 750–770). [Con86] Robert L. Constable, et. al. Implementing Mathematics with the NuPRL Proof De- velopment System. Prentice–Hall, Englewood Cliffs, NJ, 1986. [Coq85] Thierry Coquand. Une Th´eorie des Constructions. PhD thesis, University Paris VII, January 1985. [CP96] Adriana B. Compagnoni and Benjamin C. Pierce. Intersection types and mul- tiple inheritance. Mathematical Structures in Computer Science, 6(5):469–501, Oc- tober 1996. Preliminary version available as University of Edinburgh technical report ECS-LFCS-93-275 and Catholic University Nijmegen computer science technical report 93-18, Aug. 1993, under the title Multiple Inheritance via Inter- section Types. [CW85] Luca Cardelli and Peter Wegner. On understanding types, data abstraction, and polymorphism. Computing Surveys, 17(4):471–522, December 1985. January 15, 2000 BIBLIOGRAPHY 279

[dB72] Nicolas G. de Bruijn. Lambda-calculus notation with nameless dummies: a tool for automatic formula manipulation with application to the Church-Rosser theorem. Indag. Math., 34(5):381–392, 1972. [dB80] Nicolas G. de Bruijn. A survey of the project AUTOMATH. In J. P. Seldin and J. R. Hindley, editors, To H. B. Curry: Essays in Combinatory Logic, Lambda Calculus, and Formalism, pages 589–606. Academic Press, 1980. [DLP79] Richard A. De Millo, Richard J. Lipton, and Alan J. Perlis. Social processes and proofs of theorems and programs. Communications of the ACM, 22(5):271–280, May 1979. An earlier version appeared in Conference Record of the Fourth ACM Symposium on Principles of Programming Languages (POPL), 1977, pp. 206-214. [DM82] Luis Damas and Robin Milner. Principal type schemes for functional programs. In Proceedings of the 9th ACM Symposium on Principles of Programming Languages, pages 207–212, 1982. [FF98] Matthias Felleisen and Daniel P. Friedman. A little Java, A few Patterns. The MIT Press, Cambridge, Massachusetts, 1998. [Fre89] Peter J. Freyd. POLYNAT in PER. In John W. Gray and Andre Scedrov, editors, Categories in Computer Science and Logic, volume 92 of Contemporary Mathematics, pages 67–68, Providence, Rhode Island, 1989. American Mathematical Society. [FWH92] Daniel P. Friedman, Mitchell Wand, and Christopher T. Haynes. Essentials of Programming Languages. McGraw-Hill Book Co., New York, N.Y., 1992. [Ghe90] Giorgio Ghelli. Proof Theoretic Studies about a Minimal Type System Integrating Inclusion and Parametric Polymorphism. PhD thesis, Universit`a di Pisa, March 1990. Technical report TD–6/90, Dipartimento di Informatica, Universit`adi Pisa.

[Ghe95] Giorgio Ghelli. Divergence of F  type checking. Theoretical Computer Science, 139(1,2):131–162, 1995. [GHJV94] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley, Mas- sachusetts, 1994. [Gir72] Jean-Yves Girard. Interpr´etation fonctionelle etelimination ´ des coupures de l’arith- m´etique d’ordre sup´erieur. PhD thesis, Universit´e Paris VII, 1972. A summary appeared in the Proceedings of the Second Scandinavian Logic Symposium (J.E. Fenstad, editor), North-Holland, 1971 (pp. 63–92). [Gir87] Jean-Yves Girard. Linear logic. Theoretical Computer Science, 50:1–102, 1987. [GLT89] Jean-Yves Girard, Yves Lafont, and Paul Taylor. Proofs and Types, volume 7 of Cambridge Tracts in Theoretical Computer Science. Cambridge University Press, Cambridge, 1989. [GMW79] Michael J. Gordon, Robin Milner, and Christopher P. Wadsworth. Edinburgh LCF. Springer-Verlag LNCS 78, 1979. [GR83] Adele Goldberg and David Robson. Smalltalk-80: The Language and Its Imple- mentation. Addison-Wesley, Reading, MA, 1983. January 15, 2000 BIBLIOGRAPHY 280

[Gun92] C. A. Gunter. Semantics of Programming Languages: Structures and Techniques. The MIT Press, Cambridge, MA, 1992. [Hay91] S. Hayashi. Singleton, union and intersection types for program extraction. In T.Ito and A.R.Meyer, editors, Theoretical Aspect of Computer Software (Lecture Notes in Comuter Science No. 526), pages 701–730, Berlin, 1991. Springer-Verlag. [HHP92] Robert Harper, Furio Honsell, and Gordon Plotkin. A framework for defining logics. Journal of the ACM, 40(1):143–184, 1992. Preliminary version in LICS’87. [Hin97] J. Roger Hindley. Basic Simple Type Theory, volume 42 of Cambridge Tracts in Theoretical Computer Science. Cambridge University Press, Cambridge, 1997. [HL94] Robert Harper and Mark Lillibridge. A type-theoretic approach to higher-order modules with sharing. In Proceedings of the Twenty-First ACM Symposium on Principles of Programming Languages (POPL), Portland, Oregon, pages 123–137, Portland, OR, January 1994. [HMV93] My Hoang, John Mitchell, and Ramesh Viswanathan. Standard ML-NJ weak polymorphism and imperative constructs. In Proceedings, Eighth Annual IEEE Symposium on Logic in Computer Science, pages 15–25. IEEE Computer Society Press, 1993. [HO94] J. M. E. Hyland and C.-H. L. Ong. On full abstraction for PCF: I, II and III. Submitted for publication; electronic draft available through

fØÔ:»»fØÔºcÓÑÐabºÓܺacºÙk»Ô Ùb»DÓ cÙÑe ÒØ×»Ø echÔ aÔeÖ ×»ÄÙk eºÇÒ g», 1994. [How80] W. A. Howard. The formulas-as-types notion of construction. In J. P. Seldin and J. R. Hindley, editors, To H. B. Curry: Essays on Combinatory Logic, Lambda Cal- culus, and Formalism, pages 479–490. Academic Press, New York, 1980. Reprint of 1969 article. [HP95] Martin Hofmann and Benjamin Pierce. Positive subtyping. In Proceedings of Twenty-Second Annual ACM Symposium on Principles of Programming Languages, pages 186–197. ACM, January 1995. Full version in Information and Computation, volume 126, number 1, April 1996. Also available as University of Edinburgh technical report ECS-LFCS-94-303, September 1994. [HP98] Martin Hofmann and Benjamin C. Pierce. Type destructors. In Didier R´emy, editor, Informal proceedings of the Fourth International Workshop on Foundations of Object-Oriented Languages (FOOL), January 1998. Full version to appear in Theory and Practice of Object Systems.

[HS86] J. Roger Hindley and Jonathan P. Seldin. Introduction to Combinators and - Calculus, volume 1 of London Mathematical Society Student Texts. Cambridge University Press, 1986. [HU79] John E. Hopcroft and Jeffrey D. Ullman. Introduction to Automata Theory, Lan- guages, and Computation. Addison-Wesley, 1979. [IPW99] Atsushi Igarashi, Benjamin Pierce, and Philip Wadler. Featherweight Java: A minimal core calculus for Java and GJ. In Object Oriented Programing: Systems, Languages, and Applications (OOPSLA), October 1999. [JG91] Pierre Jouvelot and David Gifford. Algebraic reconstruction of types and ef- fects. In Conference Record of the Eighteenth Annual ACM Symposium on Principles January 15, 2000 BIBLIOGRAPHY 281

of Programming Languages, Orlando, Florida, pages 303–310. ACM Press, January 1991. This paper presents the first algorithm for reconstructing the types and effects of expressions in the presence of first-class procedures in a polymorphi- cally typed language. The algorithm involves a new technique called algebraic reconstruction, whose soundness and completeness properties are proved. [JMP94] L.S. van Benthem Jutting, James McKinna, and Robert Pollack. Checking algo- rithms for Pure Type Systems. In Henk Barendregt and Tobias Nipkow, editors, Proceedings of the International Workshop on Types for Proofs and Programs, pages 19–61, Nijmegen, The Netherlands, May 1994. Springer-Verlag LNCS 806.

[KCR98] Richard Kelsey, William Clinger, and Jonathan Rees. Revised 5 report on the algorithmic language Scheme. ACM SIGPLAN Notices, 33(9):26–76, September 1998. With H. Abelson, N. I. Adams, IV, D. H. Bartley, G. Brooks, R. K. Dybvig, D. P. Friedman, R. Halstead, C. Hanson, C. T. Haynes, E. Kohlbecker, D. Oxley, K. M. Pitman, G. J. Rozas, G. L. Steele, Jr., G. J. Sussman, and M. Wand. [KS92] Dinesh Katiyar and Sriram Sankar. Completely bounded quantification is de- cidable. In Proceedings of the ACM SIGPLAN Workshop on ML and its Applications, June 1992.

[LAB · 81] B. Liskov, R. Atkinson, T. Bloom, E. Moss, J.C. Schaffert, R. Scheifler, and A. Snyder. CLU Reference Manual. Springer-Verlag, 1981. [Lan64] P. J. Landin. The mechanical evaluation of expressions. Computer Journal, 6:308– 320, January 1964. [Lan65] P. J. Landin. A correspondence between ALGOL 60 and Church’s lambda- notation: Parts I and II. Communications of the ACM, 8(2,3):89–101, 158–165, February and March 1965. [Lan66] P. J. Landin. The next 700 programming languages. Communications of the ACM, 9(3):157–166, March 1966. [Ler94] Xavier Leroy. Manifest types, modules and separate compilation. In Confer- ence record of POPL ’94: 21st ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pages 109–122, Portland, OR, January 1994. [Ler95] Xavier Leroy. Applicative functors and fully transparent higher-order mod- ules. In Proceedings of the Twenty-Second ACM Symposium on Principles of Pro- gramming Languages (POPL), Portland, Oregon, pages 142–153, San Francisco, California, January 1995. [Ler96] Xavier Leroy. A syntactic theory of type generativity and sharing. Journal of Functional Programming, 6(5):667–698, September 1996. [LM91] Xavier Leroy and Michel Mauny. Dynamics in ML. In John Hughes, editor, Functional Programming Languages and Computer Architecture 1991, volume 523 of Lecture Notes in Computer Science, pages 406–426. Springer-Verlag, 1991. [LP99] Michael Y. Levin and Benjamin C. Pierce. Tinkertype: A language for playing with formal systems. Technical Report MS-CIS-99-19, Dept of CIS, University of Pennsylvania, July 1999. [Luo90] Zhaohui Luo. An Extended Calculus of Constructions. PhD thesis, Department of Computer Science, University of Edinburgh, June 1990. January 15, 2000 BIBLIOGRAPHY 282

[LW91] X. Leroy and P.Weis. Polymorphic type inference and assignment. In Eighteenth Annual ACM Symposium on Principles of Programming Languages, Orlando, FL, pages 291–302. ACM, New York, NY, 1991. [Mac86] David MacQueen. Using dependent types to express modular structure. In 13th Annual ACM Symposium on Principles of Programming languages, pages 277– 286, St. Petersburg Beach, FL, January 1986. [Mar73] Per Martin-L¨of. An intuitionistic theory of types: predicative part. In H. E. Rose and J. C. Shepherdson, editors, Logic Colloquium, ’73, pages 73–118, Ams- terdam, 1973. North Holland. [Mar82] Per Martin-L¨of. Constructive mathematics and computer programming. In Logic, Methodology and Philosophy of Science, VI. North Holland, Amsterdam, 1982. [Mar88] Simone Martini. Bounded quantifiers have interval models. In Proceedings of the ACM Conference on Lisp and Functional Programming, pages 174–183, Snowbird, Utah, July 1988. ACM.

[MCG · 99] Greg Morrisett, Karl Crary, Neal Glew, Dan Grossman, Richard Samuels, Fred- erick Smith, David Walker, Stephanie Weirich, and Steve Zdancewic. TALx86: A realistic typed assembly language. Submitted to the 1999 ACM SIGPLAN Workshop on Compiler Support for System Software, 1999. [MCGW98] Greg Morrisett, Karl Crary, Neal Glew, and David Walker. Stack-based typed assembly language. In Second International Workshop on Types in Compilation, pages 95–117, Kyoto, March 1998. Published in Xavier Leroy and Atsushi Ohori, editors, Lecture Notes in Computer Science, volume 1473, pages 28-52. Springer-Verlag, 1998. [Mil78] Robin Milner. A theory of type polymorphism in programming. Journal of Computer and System Sciences, 17:348–375, August 1978.

[Mil91] Robin Milner. The polyadic -calculus: a tutorial. Technical Report ECS–LFCS– 91–180, Laboratory for Foundations of Computer Science, Department of Com- puter Science, University of Edinburgh, UK, October 1991. Appeared in Pro- ceedings of the International Summer School on Logic and Algebra of Specification, Marktoberdorf, August 1991. Reprinted in Logic and Algebra of Specification, ed. F. L. Bauer, W. Brauer, and H. Schwichtenberg, Springer-Verlag, 1993. [Mit84a] John C. Mitchell. Coercion and type inference (summary). In Proc. 11th ACM Symp. on Principles of Programming Languages, pages 175–185, January 1984. [Mit84b] John C. Mitchell. Type inference and type containment. In Proc. Int. Symp. on Semantics of Data Types, Sophia-Antipolis (France), pages 257–278, Berlin, June 1984. Springer LNCS 173. Full version in Information and Computation, vol. 76, no. 2/3, 1988, pp. 211–249. Reprinted in Logical Foundations of Functional Pro- gramming, ed. G. Huet, Addison-Wesley (1990) 153–194. [Mit90] J. C. Mitchell. Type systems for programming languages. In J. van Leeuwen, editor, Handbook of Theoretical Computer Science, Volume B, pages 365–458. North-Holland, Amsterdam, 1990. [Mit96] John C. Mitchell. Foundations for Programming Languages. The MIT Press, Cam- bridge, MA, 1996. January 15, 2000 BIBLIOGRAPHY 283

[MP88] John C. Mitchell and Gordon D. Plotkin. Abstract types have existential types. ACM Trans. on Programming Languages and Systems, 10(3):470–502, 1988. Prelim- inary version appeared in Proc. 12th ACM Symp. on Principles of Programming Languages, 1985. [MP91] Spiro Michaylov and Frank Pfenning. Natural semantics and some of its meta- theory in Elf. In L.-H. Eriksson, L. Halln¨as, and P. Schroeder-Heister, editors, Proceedings of the Second International Workshop on Extensions of Logic Program- ming, pages 299–344, Stockholm, Sweden, January 1991. Springer-Verlag LNAI 596. [MP93] James McKinna and Robert Pollack. Pure Type Sytems formalized. In M. Bezem and J. F. Groote, editors, Proceedings of the International Conference on Typed Lambda Calculi and Applications, pages 289–305. Springer-Verlag LNCS 664, March 1993. [MPW92] R. Milner, J. Parrow, and D. Walker. A calculus of mobile processes (Parts I and II). Information and Computation, 100:1–77, 1992. [MTH90] Robin Milner, Mads Tofte, and Robert Harper. The Definition of Standard ML. The MIT Press, 1990. [MTHM97] Robin Milner, Mads Tofte, Robert Harper, and David MacQueen. The Definition of Standard ML (Revised). The MIT Press, 1997. [MWCG98] Greg Morrisett, David Walker, Karl Crary, and Neal Glew. From System F to Typed Assembly Language. In Twenty-fifth ACM Symposium on Principles of Programming Languages, pages 85–97, San Diego, January 1998.

[N· 63] P. Naur et al. Revised report on the algorithmic language 60. Communica- tions of the ACM, 6:1–17, January 1963. [Nec97] George C. Necula. Proof-carrying code. In Conference Record of POPL ’97: The 24th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Lan- guages, pages 106–119, Paris, France, 15–17 January 1997. [NL96] George C. Necula and Peter Lee. Safe kernel extensions without run-time checking. In USENIX, editor, 2nd Symposium on Operating Systems Design and Implementation (OSDI ’96), October 28–31, 1996. Seattle, WA, pages 229–243, Berkeley, CA, USA, October 1996. USENIX. [NL98] G. C. Necula and P. Lee. Safe, untrusted agents using proof-carrying code. In G. Vigna, editor, Mobile Agents and Security, volume 1419 of LNCS, pages 61–91. SV, 1998. [oD80] US Dept. of Defense. Reference Manual for the Ada Programming Language. GPO 008-000-00354-8, 1980. [OR94] Peter W. O’Hearn and Jon G. Riecke. Fully abstract translations and parametric polymorphism. In ESOP ’94: 6th European Symposium on Programming, April 1994. Springer Lecture Notes in Computer Science, volume 788. [PA93] Gordon Plotkin and Mart´ın Abadi. A logic for parametric polymorphism. In M. Bezem and J. F. Groote, editors, International Conference on Typed Lambda Cal- culi and Applications, number 664 in Lecture Notes in Computer Science, pages 361–375, Utrecht, The Netherlands, March 1993. Springer-Verlag. TLCA’93. January 15, 2000 BIBLIOGRAPHY 284

[Pfe89] Frank Pfenning. Elf: A language for logic definition and verified meta- programming. In Fourth Annual Symposium on Logic in Computer Science, pages 313–322, Pacific Grove, California, June 1989. IEEE Computer Society Press. [Pfe91] Frank Pfenning. Logic programming in the LF logical framework. In G´erard Huet and Gordon Plotkin, editors, Logical Frameworks, pages 149–181. Cam- bridge University Press, 1991. [Pfe94] Frank Pfenning. Elf: A meta-language for deductive systems. In A. Bundy, editor, Proceedings of the 12th International Conference on Automated Deduction, pages 811–815, Nancy, France, June 1994. Springer-Verlag LNAI 814. System abstract. [Pfe96] Frank Pfenning. The practice of logical frameworks. In H´el`ene Kirchner, editor, Proceedings of the Colloquium on Trees in Algebra and Programming, pages 119–134, Link¨oping, Sweden, April 1996. Springer-Verlag LNCS 1059. Invited talk. [Pie90] Benjamin C. Pierce. Preliminary investigation of a calculus with intersection and union types. Unpublished manuscript, June 1990. [Pie91a] Benjamin C. Pierce. Programming with Intersection Types and Bounded Polymor- phism. PhD thesis, Carnegie Mellon University, December 1991. Available as School of Computer Science technical report CMU-CS-91-205. [Pie91b] Benjamin C. Pierce. Programming with intersection types, union types, and polymorphism. Technical Report CMU-CS-91-106, Carnegie Mellon Univer- sity, February 1991. [Pie94] Benjamin C. Pierce. Bounded quantification is undecidable. Information and Computation, 112(1):131–165, July 1994. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Programming: Types, Se- mantics, and Language Design (MIT Press, 1994). Preliminary version in POPL ’92. [Pie97] Benjamin C. Pierce. Intersection types and bounded polymorphism. Mathemat- ical Structures in Computer Science, 7(2):129–193, April 1997. Summary version appeared in Conference on Typed Lambda Calculi and Applications, March 1993, pp. 346–360. Preliminary version available as University of Edinburgh technical report ECS-LFCS-92-200. [PJL92] Simon L. Peyton Jones and David R. Lester. Implementing Functional Languages. Prentice Hall, 1992. [Plo77] G. D. Plotkin. LCF considered as a programming language. Theoretical Com- puter Science, 5:223–255, 1977. [Pol94] Robert Pollack. The Theory of LEGO: A Proof Checker for the Extended Calculus of Constructions. PhD thesis, University of Edinburgh, 1994. [Pol96] Erik Poll. Width-subtyping and polymorphic record update. Manuscript, June 1996.

[Pot80] Garrell Pottinger. A type assignment for the strongly normalizable -terms. In To H. B. Curry: Essays on Combinatory Logic, Lambda Calculus, and Formalism, pages 561–577. Academic Press, New York, 1980. January 15, 2000 BIBLIOGRAPHY 285

[Pot97] Franc¸ois Pottier. Simplifying subtyping constraints. In Proceedings of the Inter- national Conference on Functional Programming (ICFP), 1997. [Pot98] Franc¸ois Pottier. A framework for type inference with subtyping. In Proceedings of the third ACM SIGPLAN International Conference on Functional Programming (ICFP ’98), pages 228–238, September 1998. [PS94] Jens Palsberg and Michael I. Schwartzbach. Object-Oriented Type Systems. Wiley, 1994. [PT94] Benjamin C. Pierce and David N. Turner. Simple type-theoretic foundations for object-oriented programming. Journal of Functional Programming, 4(2):207– 247, April 1994. Preliminary version in Principles of Programming Languages (POPL), 1993. [R´em89] Didier R´emy. Typechecking records and variants in a natural extension of ML. In Proceedings of the Sixteenth Annual ACM Symposium on Principles of Program- ming Languages, Austin, pages 242–249. ACM, January 1989. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Pro- gramming: Types, Semantics, and Language Design (MIT Press, 1994). [R´em90] Didier R´emy. Alg`ebres Touffues. Application au Typage Polymorphe des Objets En- registrements dans les Langages Fonctionnels. PhD thesis, Universit´e Paris VII, 1990. [Rey74] John Reynolds. Towards a theory of type structure. In Proc. Colloque sur la Programmation, pages 408–425, New York, 1974. Springer-Verlag LNCS 19. [Rey80] John Reynolds. Using category theory to design implicit conversions and generic operators. In N. D. Jones, editor, Proceedings of the Aarhus Workshop on Semantics-Directed Compiler Generation, number 94 in Lecture Notes in Com- puter Science. Springer-Verlag, January 1980. Also in Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects of Object-Oriented Programming: Types, Semantics, and Language Design (MIT Press, 1994). [Rey83] John C. Reynolds. Types, abstraction, and parametric polymorphism. In R. E. A. Mason, editor, Information Processing 83, pages 513–523, Amsterdam, 1983. Elsevier Science Publishers B. V. (North-Holland). [Rey84] J. C. Reynolds. Polymorphism is not set-theoretic. In G. Kahn, D. B. MacQueen, and G. D. Plotkin, editors, Semantics of Data Types, volume 173 of Lecture Notes in Computer Science, pages 145–156, Berlin, 1984. Springer-Verlag. [Rey88] John C. Reynolds. Preliminary design of the programming language Forsythe. Technical Report CMU-CS-88-159, Carnegie Mellon University, June 1988. [Rey98] John Reynolds. Theories of Programming Languages. Cambridge University Press, 1998. [RP] John C. Reynolds and Gordon D. Plotkin. On functors expressible in the poly- morphic lambda calculus. Submitted to Information and Computation. Also available as CMU School of Computer Science technical report number CMU- CS-90-147. [RR94] E. P. Robinson and G. Rosolini. Reflexive graphs and parametric polymor- phism. In Proceedings, Ninth Annual IEEE Symposium on Logic in Computer Sci- ence, pages 364–371, Paris, France, 4–7 July 1994. IEEE Computer Society Press. January 15, 2000 BIBLIOGRAPHY 286

[RV97] Didier R´emy and J´erˆome Vouillon. Objective ML: A simple object-oriented extension of ML. In Conference Record of POPL ’97: the 24th ACM SIGPLAN- SIGACT Symposium on Principles of Programming Languages, pages 40–53, Paris, France, January 15–17, 1997. ACM Press. Full version to appear in Theory and Practice of Object Systems, 1998. [Sch86] David A. Schmidt. Denotational Semantics: A Methodology for Language Develop- ment. Allyn and Bacon, 1986. [SJ75] and Guy Lewis Steele Jr. Scheme: an interpreter for ex- tended lambda calculus. MIT AI Memo 349, Massachusetts Institute of Tech- nology, Cambridge, Mass., December 1975. [SNP90] Jan Smith, Bengt Nordstr¨om, and Kent Petersson. Programming in Martin-L¨of’s Type Theory. An Introduction. Oxford University Press, 1990. [TB98] Tofte and Birkedal. A region inference algorithm. ACMTOPLAS: ACM Trans- actions on Programming Languages and Systems, 20, 1998. [Ten81] R. D. Tennent. Principles of Programming Languages. Prentice-Hall, 1981. [Tho91] Simon Thompson. Type Theory and Functional Programming. Addison Wesley, 1991. [TJ92] J.-P. Talpin and P. Jouvelot. The type and effects discipline. In Proc. IEEE Symp. on Logic in Computer Science, pages 162–173, 1992.

[TMC · 96] D. Tarditi, G. Morrisett, P. Cheng, C. Stone, R. Harper, and P. Lee. TIL : A type-directed for ML. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implemantation, pages 181–192, New York, May 21–24 1996. ACM Press. [Tof90] Mads Tofte. Type inference for polymorphic references. Information and Com- putation, 89(1), November 1990. [TT97] Mads Tofte and Jean-Pierre Talpin. Region-based memory management. Infor- mation and Computation, 132(2):109–176, 1 February 1997. [TvD88] A. S. Troelstra and D. van Dalen. Constructivism in Mathematics, An Introduction (vol I). North-Holland, 1988. [TWM95] David N Turner, Philip Wadler, and Christian Mossin. Once upon a type. In Functional Programming Languages and Computer Architecture, San Diego, Cali- fornia, 1995. [vBM97] J. F. A. K. van Benthem and Alice Ter Meulen, editors. Handbook of Logic and Language. MIT Press, 1997. [Wad90] Philip Wadler. Linear types can change the world. In TC 2 Working Conference on Programming Concepts and Methods (Preprint), pages 546–566, 1990. [Wad91] Philip Wadler. Is there a use for linear logic? In Proceedings of ACM Symposium on Partial Evaluation and Semantics-Based Program Manipulation, pages 255–273, 1991.

[WAL · 89] Pierre Weis, Mar´ıa-Virginia Aponte, Alain Laville, Michel Mauny, and Asc´ander Su´arez. The CAML reference manual, Version 2.6. Technical report, Projet Formel, INRIA-ENS, 1989. January 15, 2000 BIBLIOGRAPHY 287

[Wan87] Mitchell Wand. Complete type inference for simple objects. In Proceedings of the IEEE Symposium on Logic in Computer Science, Ithaca, NY, June 1987. [Wan88] Mitchell Wand. Corrigendum: Complete type inference for simple objects. In Proceedings of the IEEE Symposium on Logic in Computer Science, 1988. [Wan89] Mitchell Wand. Type inference for record concatenation and multiple inher- itance. In Fourth Annual IEEE Symposium on Logic in Computer Science, pages 92–97, Pacific Grove, CA, June 1989. [Win93] Glynn Winskel. The Formal Semantics of Programming Languages: An Introduc- tion. MIT Press, 1993. [WR25] Alfred North Whitehead and . Principia Mathematica, Volume 1. Cambridge University Press, Cambridge, 1925. [Wri92] Andrew K. Wright. Typing references by effect inference. In Bernd Krieg- Bruckner, editor, ESOP ’92, 4th European Symposium on Programming, Rennes, France, February 1992, Proceedings, volume 582 of Lecture Notes in Computer Sci- ence, pages 473–491. Springer-Verlag, New York, N.Y., 1992. Index

f F

<: (“Full” bounded quantification), 162 Dill, David, 13

k F

<: (Bounded quantification), 160

! : F < (Higher-order bounded quantification), elimination rule, 60 224 explicitly typed, 59 F ! (Higher-order polymorphic lambda-calculus), expression, see term 214

(Iso-recursive types), 115 fixed-point combinator, 38

£ !

(multi-step evaluation), 26 free variable, 33 ! (one-step evaluation), 25, 43 free variables, 40 System F(Polymorphic lambda-calculus),

133 generation lemma, see inversion lemmas !

 (Simply typed lambda-calculus), 61

higher-order functions, 34  <: (Simply typed lambda-calculus with sub- typing), 89

! identity function, 33 F (Summary), 216 implicitly typed, 59

(Untyped lambda-calculus), 43 inductive definition, 22 abstract grammar, 21 introduction rule, 60 abstract syntax tree, 24 inversion lemmas Ad-hoc polymorphism, 131 typing, 54, 62 algorithmic subtyping, 91 lambda-calculus, 31, 32 beta-reduction, 34 lambda-term, see term bound variable, 33 lexicographic induction, 19 Lipton, Richard, 13 capture-avoiding substitution, 41 Church numerals, 36 metalanguage, 33 Church-style, 59 metavariable, 33 closed term, 33 combinator, 33 nameless term, 46 Curry-style, 59 naming context, 46 Currying, 34 natural-number induction, 18 normal form, 26, 38 de Bruijn indices, 46 de Bruijn terms, 46 object, 100 DeMillo, Richard, 13 object calculus, 31 depth of a term, 24 object language, 33 derivable, 53 Overloading, 131

288 January 15, 2000 INDEX 289

Parametric polymorphism, 131 E-LETBETA, 68, 71 Perlis, Alan, 13 E-LLETBETA,75 pi-calculus, 31 E-LRCDBETA,75 preservation theorem, 54, 64, 218 E-NULL,74 principal typings, 125 E-NULLBETAF, 74 progress theorem, 55, 64, 219 E-NULLBETAT, 74 pure lambda-calculus, 32 E-PACK, 148 E-PACKBETA, 148 rules E-PRED, 25, 29 CT-ABS, 121, 256 E-PROJ,69 CT-APP, 121, 256 E-RCDBETA, 69, 204, 246 CT-ITER, 121, 256 E-RECORD, 69, 204, 246 CT-PROJ, 259 E-RECORDSUBST, 246 CT-SUCC, 121, 256 E-REF,77 CT-VAR, 121, 256 E-REF1, 77 CT-ZERO, 121, 256 E-STRUCT, 239 E-APP1, 43, 61, 77, 89, 134, 160, 210, E-STRUCTBETA, 239 216, 225, 239 E-STRUCTSUBST, 239 E-APP2, 43, 61, 77, 89, 134, 160, 210, E-SUCC, 25, 29 216, 225, 239 E-TAG,72 E-ASSIGN,77 E-TAIL,74 E-ASSIGN1, 77 E-TAILBETA,74 E-ASSIGN2, 77 E-TAPP, 134, 161, 216, 225 E-BETA, 34, 43, 49, 61, 77, 89, 134, E-UNFOLD,116 160, 210, 216, 225, 239 E-UNPACK, 148 E-BETA2, 134, 161, 214, 216, 225 E-UPDATEBETA, 204 E-BETANATIS, 26, 30 K-ALL, 214, 217, 226 E-BETANATIZ, 25, 30 K-ARROW, 211, 217, 226, 240, 248 E-BETANATPS, 25, 29 K-SINGLETON, 244 E-BETANATPZ, 25, 29 K-STRUCT, 240 E-BODYOF, 239 K-TABS, 211, 217, 226, 245 E-BOOLBETAF, 25, 29 K-TAPP, 211, 217, 226, 245 E-BOOLBETAT, 25, 29 K-TARR-SELF, 247 E-CASE,72 K-TRCD, 243, 245 E-CASEBETA,72 K-TRCD-SELF, 247 E-COERCE1, 239 K-TVAR, 211, 217, 226, 240 E-CONS1, 73 K-TYPEOF, 240 E-CONS2, 74 K-TYPROJ, 243, 245 E-DEREF,77 KEQV-HOS, 247 E-DEREF1, 77 KEQV-HOS-SINGLETON, 247 E-FOLD,116 KEQV-HOS-TARR, 247 E-FOLDBETA,115 KEQV-HOS-TRCD, 247 E-HEAD,74 KEQV-HOS-TYPE, 247 E-HEADBETA,74 KEQV-SINGLETON, 244 E-IF, 25, 29 KEQV-TARR, 245 E-ISZERO, 26, 30 KEQV-TRCD-PERM, 242, 245 E-LET, 68, 71 KF-HOS, 247 January 15, 2000 INDEX 290

KF-SINGLETON, 244 S-ALL, 161, 162, 179, 226 KF-TARR, 245 S-APP, 226 KF-TRCD, 242, 245 S-ARROW, 87, 90, 161, 226 M-RCD,71 S-EQV, 90, 226 M-VAR,71 S-RCD,91 P-RCD, 256 S-RCD-DEPTH, 87, 90, 164, 205 P-VAR, 256 S-RCD-VARIANCE, 205 Q-ALL, 214, 217, 225 S-RCD-WIDTH, 87, 90, 164, 205 Q-APP, 211, 217, 225 S-REFL, 89, 161 Q-ARROW, 81, 83, 90, 211, 217, 225, S-SOME, 171 239, 248, 249 S-TOP, 88, 89, 161, 226 Q-BETA, 210, 217, 225 S-TRANS, 87, 89, 161, 226 Q-DEF,84 S-TRCD-WIDTH, 243, 245 Q-EXT, 211, 217, 225 S-TVAR, 159–161, 226 Q-RCD-PERM, 81, 90, 205, 249 SA-ALL, 178, 179 Q-REFL, 81, 83, 90, 210, 216, 225, 239, SA-ARROW, 92, 178 248, 249 SA-RCD,92 Q-SINGLETON1, 244 SA-REFL-TVAR, 177 Q-SINGLETON2, 244 SA-TOP, 92, 177 Q-STRUCTBETA, 239 SA-TRANS-TVAR, 177 Q-SUB, 242, 244 SK-EQV, 243, 244 Q-SYMM, 81, 83, 90, 210, 217, 225, SK-SINGLETON, 244 239, 248, 249 SK-TRANS, 243, 244 Q-TABS, 211, 217, 225 SK-TRCD-DEPTH, 243, 245 Q-TRANS, 81, 83, 90, 210, 217, 225, T-ABS, 59, 61, 77, 90, 134, 161, 211, 239, 248, 249 217, 226, 240, 248 Q-TRCD, 242 T-APP, 60, 61, 77, 86, 90, 134, 161, Q-TRCD-PERM, 242 211, 218, 226, 240, 248 Q-TRCDBETA, 242 T-ASSIGN,78 Q-TRCDEXT, 242 T-BODYOF, 240 Q-TYPROJ, 242 T-CASE,72 QA-ALL, 221 T-COERCE, 240 QA-ARROW, 82, 84, 113, 221 T-CONS,74 QA-BASE, 84, 113 T-DEREF,78 QA-LOOP,113 T-EQ, 81, 84, 211, 218, 240, 248, 249 QA-RCD,82 T-FALSE, 53, 56 QA-RECL, 113 T-FIX,73 QA-RECR, 113 T-FOLD,116 QA-REDUCEL, 84, 221 T-HEAD,74 QA-REDUCER, 84, 221 T-IF, 53, 56 QA-TABS, 221 T-ISZERO, 53, 57 QA-TAPP, 221 T-LET, 68, 256 QA-TVAR, 221 T-LLET,75 RA-APP, 221 T-LOC,78 RA-BETA, 221 T-LRCD,75 RA-DEF,84 T-NIL,74 S-ABS, 226 T-NULL,74 January 15, 2000 INDEX 291

f F

T-PACK, 146, 148, 171, 215 <: : “Full” bounded quantification

8 <: T-PRED, 53, 57 [! bq full], 162

T-PROJ, 69, 205, 249 Algorithmic rules for equi-recursive

B  T-RCD, 69, 205, 246, 249 types [! ], 113

T-REF,78 Algorithmic rules for records with per-

fg  T-STRUCT, 240 mutation [! ], 82

T-SUB, 86, 90, 161, 227 Algorithmic rules for simply typed B T-SUCC, 52, 57 lambda-calculus [! ], 82

T-TABS, 133, 134, 161, 214, 218, 227 Algorithmic rules for type definitions

B ° T-TAIL,74 [! ], 84

T-TAPP, 133, 134, 161, 214, 218, 227 Algorithmic rules for F ! [], 221

fg <: T-TRUE, 53, 56 Algorithmic subtyping [! ], 92

T-UNFOLD,116 Algorithmic subtyping [], 177

fg <: T-UNIT, 68, 78 Algorithmic typing [! ], 94

T-UNPACK, 146, 148, 171, 215 Algorithmic typing [], 174 Æ T-UPDATE, 205 Arithmetic expressions [B (untyped)],

T-VAR, 60, 61, 77, 90, 134, 161, 211, 29 B 217, 226, 240 Base types [! ], 67

T-VARIANT,72 Booleans [B (untyped)], 29

k F

T-ZERO, 52, 56 Bounded existential quantification [ <: +

TA-ABS, 82, 84, 94, 113, 174, 222 9], 171 TA-APP, 82, 84, 94, 114, 174, 222 Type systems and components

k

F ! 8

TA-COND, 261 <: : Bounded quantification [ : TA-PROJ, 82, 95 < bq], 160 TA-RCD, 82, 94 Dependent functions [???], 248 TA-TABS, 174, 222 Dependent record terms (??) [???], TA-TAPP, 175, 222 246

TA-VAR, 82, 84, 94, 113, 174, 222 Dependent records [????], 249 µ XA-OTHER, 84, 113, 174, 222 Dependent records of types [!

XA-PROMOTE, 174 trcd depkind ], 245 89 XA-REC,113 Existential types [! ], 148

XA-REDUCE, 84, 222 Exposure [], 174 fiÜ General recursion [! ], 73 simple types, 58 Type systems and components

simply typed lambda-terms, 58 ! :

F < : Higher-order bounded quan-

! : size of a term, 24 tification [F< +F ], 224

Smith, Brian Cantwell, 45 ! : Higher-order existential types [F < +

soundness, 54 9], 215 stuck term, 26 Type systems and components subject expansion, 55 F ! : Higher-order polymorphic lambda-

subject reduction, see preservation calculus [System F+ µ], 214 substitution lemma, 218 Higher-order singletons [????], 247

subtype polymorphism, 131 Type systems and components

! B  : Iso-recursive types [ ],

term, 21 115 ÐeØ ÐaÞÝ

Type systems and components Lazy let bindings [! ], 75

fg ÐaÞÝ Type systems and components Lazy records [! ], 75

January 15, 2000 INDEX 292 ÐeØ

Let binding [! ], 68 unification, 125

B Äi×Ø Lists [! ], 73 unification algorithm, 126 Type systems and components unifier, 126

System F: Polymorphic lambda-calculus unify, 126 8

[! ], 133 untyped lambda-calculus, 32

fg : Polymorphic update [F < + update],

204 value, 25

fg ÐeØ Record patterns [! pat (un- variable capture, 41

typed)], 71 fg Records and tuples [! ], 69 well-founded induction, 18

Records of types [!µtrcd ], 242 well-founded set, 18 Records with permutation of fields

Y combinator, 38

fg 

[! ], 81

ÍÒiØ := References [! ], 76

Type systems and components !

 : Simply typed lambda-calculus

[! (typed)], 61

Type systems and components 

<: : Simply typed lambda-calculus

<:

with subtyping [! ], 89 EÕ

Singleton kinds [! ], 244

X Ë

Structures [! ], 238

<: fg Subtyping rules for records [! ], 90

Type systems and components !

F : Summary [System F+ µ], 216

B °

Type definitions [! ], 83  Type operators and kinding [!

µ], 210

fg ÐeØ Typed record patterns [! pat(typed)], 256

Typing rules for booleans [B (typed)],

56 Æ Typing rules for numbers [B (typed)],

56 ÍÒiØ Unit type [! ], 67

Type systems and components ! : Untyped lambda-calculus [

(untyped)], 43 <> Variants [! ], 72 type variables, 118 types, 52 typing assertions, 53 typing context, 59 typing derivation, 53 typing judgements, 53 typing relation, 53