Programming Languages Assignment #7

Similar documents
Harvard School of Engineering and Applied Sciences Computer Science 152

Introduction to System F. Lecture 18 CS 565 4/20/09

Arbitrary-rank polymorphism in (GHC) Haskell

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

Typing Data. Chapter Recursive Types Declaring Recursive Types

Flang typechecker Due: February 27, 2015

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

Simple Unification-based Type Inference for GADTs

Polymorphism. Lecture 19 CS 565 4/17/08

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

CS131 Typed Lambda Calculus Worksheet Due Thursday, April 19th

1 Introduction. 3 Syntax

Programming Languages Lecture 14: Sum, Product, Recursive Types

CS4215 Programming Language Implementation. Martin Henz

Programming Languages and Compilers (CS 421)

Typed Lambda Calculus and Exception Handling

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

Typed Racket: Racket with Static Types

CSE505, Fall 2012, Midterm Examination October 30, 2012

Programming Languages

Homework 3 COSE212, Fall 2018

Lecture #23: Conversion and Type Inference

CS153: Compilers Lecture 14: Type Checking

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

Conversion vs. Subtyping. Lecture #23: Conversion and Type Inference. Integer Conversions. Conversions: Implicit vs. Explicit. Object x = "Hello";

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

Inductive Definitions, continued

Where is ML type inference headed?

CSE 341: Programming Languages

Lecture 9: Typed Lambda Calculus

At build time, not application time. Types serve as statically checkable invariants.

Adding GADTs to OCaml the direct approach

Let Arguments Go First

Hard deadline: 3/28/15 1:00pm. Using software development tools like source control. Understanding the environment model and type inference.

CS558 Programming Languages

Lambda Calculus and Type Inference

Agenda. CS301 Session 11. Common type constructors. Things we could add to Impcore. Discussion: midterm exam - take-home or inclass?

If a program is well-typed, then a type can be inferred. For example, consider the program

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

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

Ornaments in ML. Thomas Williams, Didier Rémy. April 18, Inria - Gallium

Recitation 6: System F and Existential Types : Foundations of Programming Languages

Variables. Substitution

Types and Type Inference

Tracing Ambiguity in GADT Type Inference

Mini-ML. CS 502 Lecture 2 8/28/08

Homework 5 COSE212, Fall 2018

The Typed Racket Guide

Programming Languages Fall 2014

CSE 505, Fall 2008, Final Examination 11 December Please do not turn the page until everyone is ready.

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

CSE-321 Programming Languages 2012 Midterm

Lecture 3: Recursion; Structural Induction

Types, Expressions, and States

Agenda. CS301 Session 9. Abstract syntax: top level. Abstract syntax: expressions. The uscheme interpreter. Approaches to solving the homework problem

Simply-Typed Lambda Calculus

cs242 Kathleen Fisher Reading: Concepts in Programming Languages, Chapter 6 Thanks to John Mitchell for some of these slides.

Lambda Calculi With Polymorphism

CSE-321: Assignment 8 (100 points)

Type Declarations. Γ <num> : num [... <id> τ... ] <id> : τ Γ true : bool Γ false : bool Γ e 1 : num Γ e 2 : num Γ. {+ e 1 e 2 } : num

Type Inference Systems. Type Judgments. Deriving a Type Judgment. Deriving a Judgment. Hypothetical Type Judgments CS412/CS413

Lambda Calculi With Polymorphism

Lecture #13: Type Inference and Unification. Typing In the Language ML. Type Inference. Doing Type Inference

Unifying Nominal and Structural Ad-Hoc Polymorphism

CSE 341, Autumn 2005, Assignment 3 ML - MiniML Interpreter

Sémantique des Langages de Programmation (SemLP) DM : Region Types

CSE341: Programming Languages Lecture 11 Type Inference. Dan Grossman Spring 2016

Let Arguments Go First

Programming Languages Lecture 15: Recursive Types & Subtyping

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

Induction and Semantics in Dafny

Formal Systems and their Applications

Second-Order Type Systems

More Lambda Calculus and Intro to Type Systems

λ calculus is inconsistent

Supplementary Notes on Exceptions

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

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

CMSC 330: Organization of Programming Languages. Formal Semantics of a Prog. Lang. Specifying Syntax, Semantics

Types and Type Inference

CSE 130, Fall 2006: Final Examination

Type Checking and Type Inference

Lecture Notes on Static Semantics

The design of a programming language for provably correct programs: success and failure

CS4120/4121/5120/5121 Spring 2018 Xi Type System Specification Cornell University Version of February 18, 2018

Overloading, Type Classes, and Algebraic Datatypes

Types, Type Inference and Unification

Lambda Calculus and Type Inference

COMP 4161 NICTA Advanced Course. Advanced Topics in Software Verification. Toby Murray, June Andronick, Gerwin Klein

Types for References, Exceptions and Continuations. Review of Subtyping. Γ e:τ τ <:σ Γ e:σ. Annoucements. How s the midterm going?

Dependent types and program equivalence. Stephanie Weirich, University of Pennsylvania with Limin Jia, Jianzhou Zhao, and Vilhelm Sjöberg

Girard s System F. Chapter System F. = λ ( f :τ 2 τ 3 ) λ (g:τ 1 τ 2 ) λ (x:τ 1 ) f (g(x)) System F

Combining Programming with Theorem Proving

CIS 500 Software Foundations Fall December 6

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

Types and evaluation

Subsumption. Principle of safe substitution

CIS 500 Software Foundations Midterm I

l e t print_name r = p r i n t _ e n d l i n e ( Name : ^ r. name)

Handout 2 August 25, 2008

Transcription:

Programming Languages Assignment #7 December 2, 2007 1 Introduction This assignment has 20 points total. In this assignment, you will write a type-checker for the PolyMinML language (a language that is pretty similar to the polymorphic lambda calculus). This type checker will perform bi-directional type inference, allowing many type annotations to be inferred automatically from the context of a term. Unlike ML-style type inference, which only works for languages with predicative prenex-polymorphism, bi-directional type inference scales to much richer languages, including languages with general polymorphism (like in System F/PolyMinML) and subtyping. The downside of bi-directional type inference is that programmers must write down some typing annotations in their programs. 2 Type inference for PolyMinML Consider the following example: fun f(x : int) : unit -> unit = (fun g(y : unit) : unit = y) end In this example, the type annotations for the argument and return type of g are redundant; because f specifies its return type, we know what the type of g must be. This frequent repetition of type information makes using plain PolyMinML tedious. Take a look at how we might write and use the polymorphic identity function. if ((typefun t. fun f(x : t) : t = x) [ bool ] true) then 1 else 0 Here, the instantiation of the polymorphic function at type bool is redundant; we know that the result must be of type bool, since it is the conditional in an if expression. Thus, some expressions need type annotations, and some do not. The essence of our type-checking algorithm will be to make a syntactic distinction between expressions whose type can be inferred, and those whose types can be checked (given some context about what their type should be). The intuition is that checkable expressions appear only where their type can be determined by context, and so they don t need type annotations. Inferable expressions are what we ve primarily used in previous type checkers. These have a unique type which can be determined in a particular variable context Γ. With two different kinds of expressions, we have two forms of typing judgments:, Γ c τ, Γ i τ 1

The first says that given a type variable context and an expression variable context Γ, as well as the target type τ, we can verify that the checkable expression c has the given type τ. The second says that given similar contexts and Γ, we can deduce the unique type τ for the inferable expression i. To recap: We separate expressions into two categories, checkable and inferable. Then we have two separate judgments: one which says that given a type, we can verify a checkable expression has that type, and one which allows us to deduce the type of an inferable expression. The next two sections give a precise description of the abstract syntax and the algorithm we use to check checkable expressions and infer the types of inferable expressions. 2.1 PolyMinML Abstract Syntax inferable i ::= () x n true false primop (c 1, c 2,...) i c fun f (x : τ d ) : τ r = c if c b then i t else i f fi i [ τ ] typefun t. i checkable c ::= I (i) cfun f(x) = c cif c b then c t else c f fi i [] c i ctypefun t. c All of the inferable expressions should be familiar. For each one, we can determine its unique type using the standard typing rules. Note the places where checkable expressions c appear. If we know the type of a function (because it is inferable), we know what the type of the argument must be, so the argument need only be a checkable expression. The body of a function is also checkable, since its type is given in the function expression. Since we know the types of the arguments to primops, those expressions are also cs. Finally, we know that the conditional expression in an if must be a boolean, so that too is checkable. Any inferable expression is checkable, since we can just ignore the context and get the type using the inference algorithm (however, it is still necessary to distinguish an inferable expression from an inferable expression as a checkable expression). The form I ( i ) means an i converted into a c. The cfun expression is checkable: given the type it is supposed to have (which must be a function type), we can type-check the function as we would for a standard annotated fun. The cif expression can be checked as well, since we know the condition must be of type BOOL, and we know that the types of the branches must match the type of the whole expression. A checkable expression applied to an inferable expression is checkable: we know the return type of the function (it is the type we are checking against), and we know the domain type (it is the type of the argument). ctypefun is checkable if its body is checkable; we simply wrap the type of the body in a type. Finally, we are able to instantiate a polymorphic inferable expression at an unspecified type, provided we know what the type of the instantiation is supposed to be. All of these strategies are made precise in the next section. 2

2.2 PolyMinML Typing Rules Inferable Expressions, Γ () unit (unit), Γ n int (int), Γ true bool (true), Γ false bool (false) Γ(x) = τ, Γ x τ (var), Γ c 1 int, Γ c 2 int, Γ +(c 1, c 2 ) int (plus) etc., Γ i τ τ, Γ c τ, Γ i c τ (app) τ 1 ok τ 2 ok, Γ[f : τ 1 τ 2 ][x : τ 1 ] c τ 2, Γ fun f(x : τ 1 ) : τ 2 = c (fun), Γ c bool, Γ i t τ, Γ i f τ, Γ if c then i t else i f fi τ (if) τ ok, Γ i t.τ, Γ i[τ] [τ/t]τ (instantiate) [t], Γ i τ, Γ typefun t.i t.τ (forall) Checkable Expressions, Γ i τ τ = τ, Γ I(i) τ (inferable), Γ[f : τ 1 τ 2 ][x : τ 1 ] c τ 2, Γ cfun f(x) = c τ 1 τ 2 (cfun), Γ c τ τ, Γ i τ, Γ c i τ (app c ) [t], Γ c τ, Γ ctypefun t.c t.τ (forall c ), Γ i t.τ σ.(τ = [σ/t]τ ), Γ i[] τ (instantiate c ) 3

These rules reflect the observations we made in the last section. The trickiest one is for the checkable polymorphic instantiation (instantiate c ). Here, we require the existence of a type σ which fills in the holes in τ to get τ. Algorithmically, we can do this by structurally comparing τ and τ, and verifying that any occurence of the type variable t in τ is matched up with the same type σ in τ. 2.3 Your Job: Implement Bi-directional Type Checking The rules given in the previous section are suggestive of an algorithm, consisting of two mutually recursive functions, check and infer. Both take a set of type variables ( ), and a variable context (Γ). infer then takes an i and returns its unique type τ in that context (if it exists). check takes a c and a type τ and verifies that it is compatible with that type. Question 1. [7 points] Complete the PolyMinML type-checker by implementing the functions check and infer in the file typing.sml. These functions should meet the following specification: check : (var bool) (var typ) cexp typ unit Such that check Γ c τ returns unit if the type is consistent, or raises the exception TypeError with an informative message otherwise. infer : (var bool) (var typ) iexp unit Such that infer Γ i returns the unique type τ of i in that context, or raises the exception TypeError with an informative message if no such τ exists. Hints Avoid unnecessarily inefficient or convoluted code, and document non-trivial invariants/preconditions. Make sure to be careful about type variables, especially concerning capture and alpha-equivalence ( t.t t and u.u u are the same type). You will probably want to make use of the functions in Types and PolyMinML when implementing check and infer. However, you only need to modify typing.sml for your solution to this part of the assignment. In order to test your type checker, you need to construct test expressions directly in ML using the datatype declared in the polyminml.sml file. We have provided a number of test cases in the file testcases.sml. Tests t1, t2,... should type-check, and tests f1, f2,... should fail. Test one of these expressions with, for example: Typing.typecheck Test.t1; Make sure that you test your code, and since our test cases are not at all exhaustive, give yourself time to develop your own. 4

Question 2. [7 points] Extend the type checking algorithm and implementation to handle existential types. Be sure to: Extend the syntax to define the checkable and inferable existential terms. Define the bi-directional type checking inference rules for existentials. Extend the PolyMinML type checker with existential types. This will involve extending the files polyminml.sml (be sure to extend the abstract syntax of PolyMinML as well as the substitution functions defined in this file), types.sml and typing.sml. Suitable test cases that test both well-typed and ill-typed expressions. Question 3. [6 points] Extend the inference rules for type checking given in question 1 so they handle subtyping. In this question, make your typing rules as general as possible. You do not need to define the subtyping relation, just the checkable and inferable rules. You may assume that given two types τ 1 and τ 2 that the relation τ 1 <= τ 2 is decidable. You may NOT assume that there is a join function join(τ 1, τ 2 ). You must complete your solution in the most general way you can without using such a relation. You do NOT have to implement this question! Just define the rules. 5