CIS 500 Software Foundations Fall December 4

Similar documents
CIS 500 Software Foundations Fall December 6

Administrivia. Existential Types. CIS 500 Software Foundations Fall December 6. Administrivia. Motivation. Motivation

Type Systems. Parametric Polymorphism. 1. Recall Let-Polymorphism. 1. Recall Let-Polymorphism. Lecture 9 Dec. 15th, 2004 Sebastian Maneth

Lambda Calculi With Polymorphism

Lambda Calculi With Polymorphism

Lesson 11 Universal Types. Universal Types and System F

Part III. Chapter 15: Subtyping

CIS 500 Software Foundations Midterm I

Polymorphic lambda calculus Princ. of Progr. Languages (and Extended ) The University of Birmingham. c Uday Reddy

Chapter 22: Type Reconstruction (Type Inference)

CIS 500 Software Foundations Fall September 25

CIS 500 Software Foundations Midterm I Answer key October 8, 2003

The Lambda Calculus. 27 September. Fall Software Foundations CIS 500. The lambda-calculus. Announcements

Part III Chapter 15: Subtyping

Lambda Calculus. Type Systems, Lectures 3. Jevgeni Kabanov Tartu,

Chapter 5: The Untyped Lambda Calculus

Type Systems Winter Semester 2006

Fall 2013 Midterm Exam 10/22/13. This is a closed-book, closed-notes exam. Problem Points Score. Various definitions are provided in the exam.

Subsumption. Principle of safe substitution

Resources: The slides of this lecture were derived from [Järvi], with permission of the original author, by copy & x = 1 let x = 1 in...

The Untyped Lambda Calculus

The University of Nottingham SCHOOL OF COMPUTER SCIENCE A LEVEL 4 MODULE, SPRING SEMESTER MATHEMATICAL FOUNDATIONS OF PROGRAMMING ANSWERS

Programming Language Concepts: Lecture 19

λ calculus Function application Untyped λ-calculus - Basic Idea Terms, Variables, Syntax β reduction Advanced Formal Methods

Lecture 9: Typed Lambda Calculus

Introduction to Lambda Calculus. Lecture 7 CS /08/09

Introduction to Lambda Calculus. Lecture 5 CS 565 1/24/08

λ-calculus Lecture 1 Venanzio Capretta MGS Nottingham

Introduction to the Lambda Calculus

Logical Verification Course Notes. Femke van Raamsdonk Vrije Universiteit Amsterdam

Introduction to dependent types in Coq

Formal Systems and their Applications

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

Lecture slides & distribution files:

CMSC 330: Organization of Programming Languages

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Lesson 4 Typed Arithmetic Typed Lambda Calculus

Types and Programming Languages. Lecture 5. Extensions of simple types

CMSC 336: Type Systems for Programming Languages Lecture 5: Simply Typed Lambda Calculus Acar & Ahmed January 24, 2008

Advances in Programming Languages

Costly software bugs that could have been averted with type checking

11/6/17. Outline. FP Foundations, Scheme. Imperative Languages. Functional Programming. Mathematical Foundations. Mathematical Foundations

Programming Language Features. CMSC 330: Organization of Programming Languages. Turing Completeness. Turing Machine.

CMSC 330: Organization of Programming Languages

Concepts of programming languages

5. Introduction to the Lambda Calculus. Oscar Nierstrasz

Universes. Universes for Data. Peter Morris. University of Nottingham. November 12, 2009

Goal. CS152: Programming Languages. Lecture 15 Parametric Polymorphism. What the Library Likes. What The Client Likes. Start simpler.

Programming Languages Fall 2014

The Untyped Lambda Calculus

Lambda Calculus. Lecture 4 CS /26/10

Less naive type theory

Lecture 13: Subtyping

Subtyping. Lecture 13 CS 565 3/27/06

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011

Harvard School of Engineering and Applied Sciences Computer Science 152

Types and Programming Languages. Lecture 8. Recursive type

Type Systems Winter Semester 2006

The Untyped Lambda Calculus

Symmetry in Type Theory

CS-XXX: Graduate Programming Languages. Lecture 9 Simply Typed Lambda Calculus. Dan Grossman 2012

Type assignment for intersections and unions in call-by-value languages

λ calculus is inconsistent

Type Systems. Pierce Ch. 3, 8, 11, 15 CSE

On Agda JAIST/AIST WS CVS/AIST Yoshiki Kinoshita, Yoriyuki Yamagata. Agenda

CS152: Programming Languages. Lecture 7 Lambda Calculus. Dan Grossman Spring 2011

More Lambda Calculus and Intro to Type Systems

Polymorphism and System-F (OV)

Type Checking and Type Inference

Review. CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Let bindings (CBV) Adding Stuff. Booleans and Conditionals

COMP 1130 Lambda Calculus. based on slides by Jeff Foster, U Maryland

Lecture 15 CIS 341: COMPILERS

Lambda Calculus and Type Inference

Type raising, continuations, and classical logic

Inductive Definitions, continued

上海交通大学试卷 ( A 卷 ) ( 2015 至 2016 学年第 2 学期 )

Lecture 3: Typed Lambda Calculus and Curry-Howard

Lecture Notes on Data Representation

9/23/2014. Why study? Lambda calculus. Church Rosser theorem Completeness of Lambda Calculus: Turing Complete

Whereweare. CS-XXX: Graduate Programming Languages. Lecture 7 Lambda Calculus. Adding data structures. Data + Code. What about functions

CIS 500 Software Foundations Fall October 2

Hiding local state in direct style: a higher-order anti-frame rule

Mathematics for Computer Scientists 2 (G52MC2)

Fundamentals and lambda calculus. Deian Stefan (adopted from my & Edward Yang s CSE242 slides)

More Lambda Calculus and Intro to Type Systems

Second-Order Type Systems

Lambda Calculus and Type Inference

An Introduction to Programming and Proving in Agda (incomplete draft)

Programming with Math and Logic

M. Snyder, George Mason University LAMBDA CALCULUS. (untyped)

Automated Reasoning. Natural Deduction in First-Order Logic

Lecture 14: Recursive Types

Functions as data. Massimo Merro. 9 November Massimo Merro The Lambda language 1 / 21

Lambda Calculus: Implementation Techniques and a Proof. COS 441 Slides 15

HOL DEFINING HIGHER ORDER LOGIC LAST TIME ON HOL CONTENT. Slide 3. Slide 1. Slide 4. Slide 2 WHAT IS HIGHER ORDER LOGIC? 2 LAST TIME ON HOL 1

上海交通大学试卷 ( A 卷 ) ( 2015 至 2016 学年第 2 学期 )

CS 6110 S11 Lecture 25 Typed λ-calculus 6 April 2011

4.8 Dependent Types 97

Official Survey. Cunning Plan: Focus On Objects. The Need for a Calculus. Object Calculi Summary. Why Not Use λ-calculus for OO?

1 Introduction. 3 Syntax

Transcription:

CIS 500 Software Foundations Fall 2006 December 4

Administrivia

Homework 11 Homework 11 is currently due on Friday. Should we make it due next Monday instead?

More on Evaluation Contexts

Progress for FJ Theorem [Progress]: Suppose t is a closed, well-typed normal form. Then either 1. t is a value, or 2. t t for some t, or 3. for some evaluation context E, we can express t as with D : C. t = E[(C)(new D(v))]

Evaluation Contexts E ::= evaluation contexts [ ] hole E.f field access E.m(t) method invocation (rcv) v.m(v,e,t) method invocation (arg) new C(v,E,t) object creation (arg) (C)E cast E.g., [].fst [].fst.snd new C(new D(), [].fst.snd, new E())

Evaluation Contexts E[t] denotes the term obtained by filling the hole in E with t. E.g., if E = (A)[], then E[(new Pair(new A(), new B())).fst] = (A)((new Pair(new A(), new B())).fst)

Evaluation Contexts Evaluation contexts capture the notion of the next subterm to be reduced : By ordinary evaluation relation: (A)((new Pair(new A(), new B())).fst) (A)(new A()) by E-Cast with subderivation E-ProjNew. By evaluation contexts: E = (A)[] r = (new Pair(new A(), new B())).fst r = new A() r r by E-ProjNew E[r] = (A)((new Pair(new A(), new B())).fst) E[r ] = (A)(new A())

Precisely... Claim 1: If r r by one of the computation rules E-ProjNew, E-InvkNew, or E-CastNew and E is an arbitrary evaluation context, then E[r] E[r ] by the ordinary evaluation relation. Claim 2: If t t by the ordinary evaluation relation, then there are unique E, r, and r such that 1. t = E[r], 2. t = E[r ], and 3. r r by one of the computation rules E-ProjNew, E-InvkNew, or E-CastNew. Proofs: Homework 11.

The Curry-Howard Correspondence

Intro vs. elim forms An introduction form for a given type gives us a way of constructing elements of this type. An elimination form for a type gives us a way of using elements of this type.

The Curry-Howard Correspondence In constructive logics, a proof of P must provide evidence for P. law of the excluded middle not recognized. P P A proof of P Q is a pair of evidence for P and evidence for Q. A proof of P Q is a procedure for transforming evidence for P into evidence for Q.

Propositions as Types Logic Programming languages propositions types proposition P Q type P Q proposition P Q type P Q proof of proposition P term t of type P proposition P is provable type P is inhabited (by some term)??? evaluation

Propositions as Types Logic propositions proposition P Q proposition P Q proof of proposition P proposition P is provable proof simplification (a.k.a. cut elimination ) Programming languages types type P Q type P Q term t of type P type P is inhabited (by some term) evaluation

Universal Types

Motivation In the simply typed lambda-calculus, we often have to write several versions of the same code, differing only in type annotations. doublenat = λf:nat Nat. λx:nat. f (f x) doublercd = λf:{l:bool} {l:bool}. λx:{l:bool}. f (f x) doublefun = λf:(nat Nat) (Nat Nat). λx:nat Nat. f (f x) Bad! Violates a basic principle of software engineering: Write each piece of functionality once

Motivation In the simply typed lambda-calculus, we often have to write several versions of the same code, differing only in type annotations. doublenat = λf:nat Nat. λx:nat. f (f x) doublercd = λf:{l:bool} {l:bool}. λx:{l:bool}. f (f x) doublefun = λf:(nat Nat) (Nat Nat). λx:nat Nat. f (f x) Bad! Violates a basic principle of software engineering: Write each piece of functionality once... and parameterize it on the details that vary from one instance to another.

Motivation In the simply typed lambda-calculus, we often have to write several versions of the same code, differing only in type annotations. doublenat = λf:nat Nat. λx:nat. f (f x) doublercd = λf:{l:bool} {l:bool}. λx:{l:bool}. f (f x) doublefun = λf:(nat Nat) (Nat Nat). λx:nat Nat. f (f x) Bad! Violates a basic principle of software engineering: Write each piece of functionality once... and parameterize it on the details that vary from one instance to another. Here, the details that vary are the types!

Idea We d like to be able to take a piece of code and abstract out some type annotations. We ve already got a mechanism for doing this with terms: λ-abstraction. So let s just re-use the notation. Abstraction: double = λx. λf:x X. λx:x. f (f x) Application: double [Nat] double [Bool] Computation: double [Nat] λf:nat Nat. λx:nat. f (f x) (N.b.: Type application is commonly written t [T], though t T would be more consistent.)

Idea What is the type of a term like λx. λf:x X. λx:x. f (f x)? This term is a function that, when applied to a type X, yields a term of type (X X) X X.

Idea What is the type of a term like λx. λf:x X. λx:x. f (f x)? This term is a function that, when applied to a type X, yields a term of type (X X) X X. I.e., for all types X, it yields a result of type (X X) X X.

Idea What is the type of a term like λx. λf:x X. λx:x. f (f x)? This term is a function that, when applied to a type X, yields a term of type (X X) X X. I.e., for all types X, it yields a result of type (X X) X X. We ll write it like this: X. (X X) X X

System F System F (aka the polymorphic lambda-calculus ) formalizes this idea by extending the simply typed lambda-calculus with type abstraction and type application. t ::= terms x variable λx:t.t abstraction t t application λx.t type abstraction t [T] type application

System F System F (aka the polymorphic lambda-calculus ) formalizes this idea by extending the simply typed lambda-calculus with type abstraction and type application. t ::= terms x variable λx:t.t abstraction t t application λx.t type abstraction t [T] type application v ::= values λx:t.t abstraction value λx.t type abstraction value

System F: new evaluation rules t 1 t 1 t 1 [T 2 ] t 1 [T 2] (λx.t 12 ) [T 2 ] [X T 2 ]t 12 (E-TApp) (E-TappTabs)

System F: Types To talk about the types of terms abstracted on types, we need to introduce a new form of types: T ::= types X type variable T T type of functions X.T universal type

System F: Typing Rules x:t Γ Γ x : T (T-Var) Γ, x:t 1 t 2 : T 2 Γ λx:t 1.t 2 : T 1 T 2 (T-Abs) Γ t 1 : T 11 T 12 Γ t 2 : T 11 Γ t 1 t 2 : T 12 (T-App) Γ, X t 2 : T 2 Γ λx.t 2 : X.T 2 (T-TAbs) Γ t 1 : X.T 12 Γ t 1 [T 2 ] : [X T 2 ]T 12 (T-TApp)

History Interestingly, System F was invented independently and almost simultaneously by a computer scientist (John Reynolds) and a logician (Jean-Yves Girard). Their results look very different at first sight one is presented as a tiny programming language, the other as a variety of second-order logic. The similarity (indeed, isomorphism!) between them is an example of the Curry-Howard Correspondence.

Examples

Lists cons : X. X List X List X head : X. List X X tail : X. List X List X nil : X. List X isnil : X. List X Bool map = λx. λy. λf: X Y. (fix (λm: (List X) (List Y). λl: List X. if isnil [X] l then nil [Y] else cons [Y] (f (head [X] l)) (m (tail [X] l)))); l = cons [Nat] 4 (cons [Nat] 3 (cons [Nat] 2 (nil [Nat]))); head [Nat] (map [Nat] [Nat] (λx:nat. succ x) l);

Church Booleans CBool = X.X X X; tru = λx. λt:x. λf:x. t; fls = λx. λt:x. λf:x. f; not = λb:cbool. λx. λt:x. λf:x. b [X] f t;

Church Numerals CNat = X. (X X) X X; c 0 = λx. λs:x X. λz:x. z; c 1 = λx. λs:x X. λz:x. s z; c 2 = λx. λs:x X. λz:x. s (s z); csucc = λn:cnat. λx. λs:x X. λz:x. s (n [X] s z); cplus = λm:cnat. λn:cnat. m [CNat] csucc n;

Properties of System F Preservation and Progress: unchanged. (Proofs similar to what we ve seen.) Strong normalization: every well-typed program halts. (Proof is challenging!) Type reconstruction: undecidable (major open problem from 1972 until 1994, when Joe Wells solved it).

Parametricity Observation: Polymorphic functions cannot do very much with their arguments. The type X. X X X has exactly two members (up to observational equivalence). X. X X has one. etc. The concept of parametricity gives rise to some useful free theorems...

Existential Types

Motivation If universal quantifiers are useful in programming, then what about existential quantifiers?

Motivation If universal quantifiers are useful in programming, then what about existential quantifiers? Rough intuition: Terms with universal types are functions from types to terms. Terms with existential types are pairs of a type and a term.

Concrete Intuition Existential types describe simple modules: An existentially typed value is introduced by pairing a type with a term, written {*S,t}. (The star avoids syntactic confusion with ordinary pairs.) A value {*S,t} of type { X,T} is a module with one (hidden) type component and one term component. Example: p = {*Nat, {a=5, f=λx:nat. succ(x)}} has type { X, {a:x, f:x X}} The type component of p is Nat, and the value component is a record containing a field a of type X and a field f of type X X, for some X (namely Nat).

The same package p = {*Nat, {a=5, f=λx:nat. succ(x)}} also has type { X, {a:x, f:x Nat}}, since its right-hand component is a record with fields a and f of type X and X Nat, for some X (namely Nat). This example shows that there is no automatic ( best ) way to guess the type of an existential package. The programmer has to say what is intended. We re-use the ascription notation for this: p = {*Nat, {a=5, f=λx:nat. succ(x)}} as { X, {a:x, f:x X}} p1 = {*Nat, {a=5, f=λx:nat. succ(x)}} as { X, {a:x, f:x Nat}} This gives us the introduction rule for existentials: Γ t 2 : [X U]T 2 Γ {*U,t 2 } as { X,T 2 } : { X,T 2 } (T-Pack)

Different representations... Note that this rule permits packages with different hidden types to inhabit the same existential type. Example: p2 = {*Nat, 0} as { X,X} p3 = {*Bool, true} as { X,X}

Different representations... Note that this rule permits packages with different hidden types to inhabit the same existential type. Example: p2 = {*Nat, 0} as { X,X} p3 = {*Bool, true} as { X,X} More useful example: p4 = {*Nat, {a=0, f=λx:nat. succ(x)}} as { X, {a:x, f:x Nat}} p5 = {*Bool, {a=true, f=λx:bool. 0}} as { X, {a:x, f:x Nat}}

Exercise... Here are three more variations on the same theme: p6 = {*Nat, {a=0, f=λx:nat. succ(x)}} as { X, {a:x, f:x X}} p7 = {*Nat, {a=0, f=λx:nat. succ(x)}} as { X, {a:x, f:nat X}} p8 = {*Nat, {a=0, f=λx:nat. succ(x)}} as { X, {a:nat, f:nat Nat}} In what ways are these less useful than p4 and p5? p4 = {*Nat, {a=0, f=λx:nat. succ(x)}} as { X, {a:x, f:x Nat}} p5 = {*Bool, {a=true, f=λx:bool. 0}} as { X, {a:x, f:x Nat}}

The elimination form for existentials Intuition: If an existential package is like a module, then eliminating (using) such a package should correspond to open or import. I.e., we should be able to use the components of the module, but the identity of the type component should be held abstract. Γ t 1 : { X,T 12 } Γ, X, x:t 12 t 2 : T 2 Γ let {X,x}=t 1 in t 2 : T 2 (T-Unpack) Example: if p4 = {*Nat, {a=0, f=λx:nat. succ(x)}} as { X,{a:X,f:X Nat}} then let {X,x} = p4 in (x.f x.a) has type Nat (and evaluates to 1).

Abstraction However, if we try to use the a component of p4 as a number, typechecking fails: p4 = {*Nat, {a=0, f=λx:nat. succ(x)}} as { X,{a:X,f:X Nat}} let {X,x} = p4 in (succ x.a) = Error: argument of succ is not a number This failure makes good sense, since we saw that another package with the same existential type as p4 might use Bool or anything else as its representation type. Γ t 1 : { X,T 12 } Γ, X, x:t 12 t 2 : T 2 Γ let {X,x}=t 1 in t 2 : T 2 (T-Unpack)

Computation The computation rule for existentials is also straightforward: let {X,x}=({*T 11,v 12 } as T 1 ) in t 2 [X T 11 ][x v 12 ]t 2 (E-UnpackPack)

Example: Abstract Data Types counteradt = {*Nat, {new = 1, get = λi:nat. i, inc = λi:nat. succ(i)}} as { Counter, {new: Counter, get: Counter Nat, inc: Counter Counter}}; let {Counter,counter} = counteradt in counter.get (counter.inc counter.new);

Representation independence We can substitute another implementation of counters without affecting the code that uses counters: counteradt = {*{x:nat}, {new = {x=1}, get = λi:{x:nat}. i.x, inc = λi:{x:nat}. {x=succ(i.x)}}} as { Counter, {new: Counter, get: Counter Nat, inc: Counter Counter}};

Cascaded ADTs We can use the counter ADT to define new ADTs that use counters in their internal representations: let {Counter,counter} = counteradt in let {FlipFlop,flipflop} = {*Counter, {new = counter.new, read = λc:counter. iseven (counter.get c), toggle = λc:counter. counter.inc c, reset = λc:counter. counter.new}} as { FlipFlop, {new: FlipFlop, read: FlipFlop Bool, toggle: FlipFlop FlipFlop, reset: FlipFlop FlipFlop}} i flipflop.read (flipflop.toggle (flipflop.toggle flipflop.new));

Existential Objects Counter = { X, {state:x, methods: {get:x Nat, inc:x X}}}; c = {*Nat, {state = 5, methods = {get = λx:nat. x, inc = λx:nat. succ(x)}}} as Counter; let {X,body} = c in body.methods.get(body.state);

Existential objects: invoking methods More generally, we can define a little function that sends the get message to any counter: sendget = λc:counter. let {X,body} = c in body.methods.get(body.state);

Invoking the inc method of a counter object is a little more complicated. If we simply do the same as for get, the typechecker complains let {X,body} = c in body.methods.inc(body.state); = Error: Scoping error! because the type variable X appears free in the type of the body of the let. Indeed, what we ve written doesn t make intuitive sense either, since the result of the inc method is a bare internal state, not an object.

To satisfy both the typechecker and our informal understanding of what invoking inc 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: c1 = let {X,body} = c in {*X, {state = body.methods.inc(body.state), methods = body.methods}} as Counter; More generally, to send the inc message to a counter, we can write: sendinc = λc:counter. let {X,body} = c in {*X, {state = body.methods.inc(body.state), methods = body.methods}} as Counter;

Objects vs. ADTs The examples of ADTs and objects that we have seen in the past few slides offer a revealing way to think about the differences between classical ADTs and objects. Both can be represented using existentials With ADTs, each existential package is opened as early as possible (at creation time) With objects, the existential package is opened as late as possible (at method invocation time) These differences in style give rise to the well-known pragmatic differences between ADTs and objects: ADTs support binary operations objects support multiple representations

A full-blown existential object model What we ve done so far is to give an account of object-style encapsulation in terms of existential types. To give a full model of all the core OO features we have discussed before, some significant work is required. In particular, we must add: subtyping (and bounded quantification ) type operators ( higher-order subtyping )