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

Similar documents
Type Systems Winter Semester 2006

CS 6110 S14 Lecture 1 Introduction 24 January 2014

CIS 500 Software Foundations Fall September 25

1 Scope, Bound and Free Occurrences, Closed Terms

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

Types, Type Inference and Unification

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

1 Introduction. 3 Syntax

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

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

Pure Lambda Calculus. Lecture 17

Concepts of programming languages

Lambda Calculus alpha-renaming, beta reduction, applicative and normal evaluation orders, Church-Rosser theorem, combinators

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

Lambda Calculus. Lecture 4 CS /26/10

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

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

CS 4110 Programming Languages & Logics. Lecture 17 Programming in the λ-calculus

Introduction to the Lambda Calculus. Chris Lomont

Exercise 1 ( = 24 points)

CSE-321 Programming Languages 2011 Final

λ calculus is inconsistent

Denotational Semantics; Lambda Calculus Basics Section and Practice Problems Week 4: Tue Feb 13 Fri Feb 16, 2018

Exercise 1 ( = 18 points)

Harvard School of Engineering and Applied Sciences Computer Science 152

Fundamentals and lambda calculus

Lambda Calculus. Lambda Calculus

5. Introduction to the Lambda Calculus. Oscar Nierstrasz

Introduction to the Lambda Calculus

Module 6. Knowledge Representation and Logic (First Order Logic) Version 2 CSE IIT, Kharagpur

Chapter 5: The Untyped Lambda Calculus

Lecture #23: Conversion and Type Inference

CSE-321 Programming Languages 2012 Midterm

Variables. Substitution

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

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

CITS3211 FUNCTIONAL PROGRAMMING

Lambda Calculus. Variables and Functions. cs3723 1

CSE-321 Programming Languages 2010 Final

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

Overview. A normal-order language. Strictness. Recursion. Infinite data structures. Direct denotational semantics. Transition semantics

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

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

CSCI.4430/6969 Programming Languages Lecture Notes

Pure (Untyped) λ-calculus. Andrey Kruglyak, 2010

CSE-321 Programming Languages 2010 Midterm

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

CMSC 330: Organization of Programming Languages. Lambda Calculus

Foundations. Yu Zhang. Acknowledgement: modified from Stanford CS242

Lambda Calculus and Type Inference

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

CSE505, Fall 2012, Midterm Examination October 30, 2012

CIS 500 Software Foundations Midterm I

CMPUT 325 : Lambda Calculus Basics. Lambda Calculus. Dr. B. Price and Dr. R. Greiner. 13th October 2004

CSE 505: Concepts of Programming Languages

CS 4110 Programming Languages & Logics. Lecture 28 Recursive Types

Type Inference; Parametric Polymorphism; Records and Subtyping Section and Practice Problems Mar 20-23, 2018

CSE-321 Programming Languages 2014 Final

Typed Lambda Calculus and Exception Handling

One of a number of approaches to a mathematical challenge at the time (1930): Constructibility

Programming Languages Assignment #7

The Typed λ Calculus and Type Inferencing in ML

Exercise 1 (2+2+2 points)

CMSC 330: Organization of Programming Languages

ML 4 Unification Algorithm

Lecture 9: Typed Lambda Calculus

CMSC 330: Organization of Programming Languages. Lambda Calculus

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

Math 233. Lagrange Multipliers Basics

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

Constraint-based Analysis. Harry Xu CS 253/INF 212 Spring 2013

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

Types, Expressions, and States

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

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

Advanced Seminar Softwareengineering - Denotational semantics

CS422 - Programming Language Design

Lecture Notes on Data Representation

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

Lambda expressions, functions and binding

Untyped Lambda Calculus

Organization of Programming Languages CS3200/5200N. Lecture 11

Introduction to the λ-calculus

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

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

Activity. CSCI 334: Principles of Programming Languages. Lecture 4: Fundamentals II. What is computable? What is computable?

Lecture #3: Lambda Calculus. Last modified: Sat Mar 25 04:05: CS198: Extra Lecture #3 1

The Metalanguage λprolog and Its Implementation

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

TYPE INFERENCE. François Pottier. The Programming Languages Mentoring ICFP August 30, 2015

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

Untyped Lambda Calculus

Hw 4 Due Feb 22. D(fg) x y z (

CS 4110 Programming Languages & Logics. Lecture 27 Recursive Types

Type Checking and Type Inference

Functional Programming. Overview. Topics. Recall λ-terms. Examples

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

Mutable References. Chapter 1

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

Lecture Note: Types. 1 Introduction 2. 2 Simple Types 3. 3 Type Soundness 6. 4 Recursive Types Subtyping 17

Transcription:

CS 6110 S18 Lecture 24 Type Inference and Unification 1 Type Inference Type inference refers to the process of determining the appropriate types for expressions based on how they are used. For example, OCaml knows that in the expression (f 3), f must be a function (because it is applied to something, not because its name is f!) and that it takes an int as input. It knows nothing about the output type. Therefore the type inference mechanism of OCaml would assign f the type int -> a. # fun f -> f 3;; - : (int -> a) -> a = <fun> There may be many different occurrences of a symbol in an expression, all leading to different typing constraints, and these constraints must have a common solution, otherwise the expression cannot be typed. # fun f -> f (f 3);; - : (int -> int) -> int = <fun> # fun f -> f (f "hi");; - : (string -> string) -> string = <fun> # fun f -> f (f 3, f 4);; Error: This expression has type a * a but an expression was expected of type int In the first example, how does it know that the output type of f is int? Because the input type of f is int, and the output of f is fed into f again, so the output type of f has to be the same as the input type of f. If a program is well-typed, then a type can be inferred. For example, consider the program let square = λz. z z in λf. λx. λy. if (f x y) then (f (square x) y) else (f x (f x y)) We are applying the multiplication operator to z, therefore we must have z : int, thus λz. z z : int int and square : int int. We know that the type of f must be something of the form f : σ τ bool for some σ and τ, since it is applied to two arguments and its return value is used in a conditional test. Since f is applied to the value of square x as its first argument, it must be that σ = int. Since f is applied to the value of f x y as its second argument, it must be that τ = bool. Thus f must be of type int bool bool, x must be of type int, and y must be of type bool. The value of the program is a function that takes inputs f, x, and y, and returns a bool. Thus the type of the entire program is (int bool bool) int bool bool. 2 Unification Both type inference and pattern matching in OCaml are instances of a very general mechanism called unification. Briefly, unification is the process of finding a substitution that makes two given terms equal. Pattern matching in OCaml is done by applying unification to OCaml expressions, whereas type inference is 1

done by applying unification to type expressions. It is interesting that both these procedures turn out to be applications of the same general mechanism. There are many other applications of unification in computer science; for example, the programming language Prolog is based on it. Let us write ss for the result of applying a substitution S to the term s. For example, f(x, h(x, y)){g(y)/x, z/y} = f(g(y), h(g(y), z)), where the substitution operator {g(y)/x, z/y} applied to a term simultaneously substitutes g(y) for x and z for y. The substitution is simultaneous, not sequential. In this example, sequential substitution gives a different result: f(x, h(x, y)){g(y)/x}{z/y} = f(g(y), h(g(y), y)){z/y} = f(g(z), h(g(z), z)). The essential task of unification is to find a substitution S that unifies two given terms (makes them equal). Thus, given s and t, we want to find S such that ss = ts. Such a substitution S is called a unifier for s and t. For example, given the terms the substitution would be a unifier, since f(x, g(y)) f(g(z), w) (1) S = {g(z)/x, g(y)/w} (2) f(x, g(y)){g(z)/x, g(y)/w} = f(g(z), w){g(z)/x, g(y)/w} = f(g(z), g(y)). Note that this is a purely syntactic definition; the meaning of expressions is not taken into consideration when computing unifiers. Unifiers do not necessarily exist. For example, the terms x and f(x) cannot be unified, since no substitution for x can make the two terms equal. Even when unifiers exist, they are not necessarily unique. For example, the substitution T = {g(f(a, b))/x, f(b, a)/y, f(a, b)/z, g(f(b, a))/w} is also a unifier for the two terms (1): f(x, g(y)) T = f(g(z), w) T = f(g(f(a, b)), g(f(b, a))). However, when a unifier exists, there is always a most general unifier (mgu) that is unique up to renaming. A unifier S for s and t is a most general unifier (mgu) for s and t if S is a unifier for s and t, any other unifier T for s and t is a refinement of S; that is, T can be obtained from S by doing further substitutions. For example, the substitution S in the example above is an mgu for f(x, g(y)) and f(g(z), w). The unifier T is a refinement of S, since T = S U, where U = {f(a, b)/z, f(b, a)/y}. 2

Note that f(x, g(y)) S U = f(x, g(y)){g(z)/x, g(y)/w}{f(a, b)/z, f(b, a)/y} = f(g(z), g(y)){f(a, b)/z, f(b, a)/y} = f(g(f(a, b)), g(f(b, a))) = f(x, g(y)) T. We can compose substitutions, as we did with S U. This is the substitution that first applies S, then applies U to the result. The composition is also a substitution. 3 Unification Algorithm The unification algorithm is known as Robinson s algorithm (1965). We need unification for not just for a pair of terms, but more generally, for a set of pairs of terms. We say that a substitution S is a unifier for a set of pairs {(s 1, t 1 ),..., (s n, t n )} if s i S = t i S for all 1 i n. The unification algorithm is given in terms of a function Unify that takes a set of (unordered) pairs of terms (s, t) and produces their mgu, if it exists. If E is a set of pairs of terms, then E {t/x} denotes the result of applying the substitution {t/x} to all the terms in E. Unify({(x, t)} E) {t/x} Unify(E {t/x}) if x / FV(t) Unify( ) I (the identity substitution x x) Unify({(x, x)} E) Unify(E) Unify({(f(s 1,..., s n ), f(t 1,..., t n ))} E) Unify({(s 1, t 1 ),..., (s n, t n )} E). In the first rule, {t/x} denotes the substitution that substitutes t for x, and {t/x} Unify(E {t/x}) denotes the composition of {t/x} and Unify(E {t/x}). Since we write substitutions on the right, we follow the convention that composition is from left to right; thus S T means, do S, then do T. The algorithm will fail if it ever encounters a pair (x, t) such that x t but x occurs in t or a pair (f(s 1,..., s m ), g(t 1,..., t n )) such that f g. In either case, no substitution can unify the two terms. 4 Type Inference and Unification Now we show how to do type inference using unification on type expressions. This technique gives the most general type (mgt) of any typable term; any other type of this term is a substitution instance of its most general type. Recall the Curry-style simply typed λ-calculus with syntax and typing rules e ::= x e 1 e 2 λx. e τ ::= α τ 1 τ 2 Γ, x : τ x : τ Γ e 1 : σ τ Γ e 2 : σ Γ (e 1 e 2 ) : τ Γ, x : σ e : τ Γ λx. e : σ τ. For the language of types, the last unification rule translates to Unify({(s s, t t )} E) Unify({(s, t), (s, t )} E). 3

The problem is that any type derivation starts with assumptions about the types of the variables in the form of a type environment Γ, but without a type environment or an annotation as in Church style, we do not know what these are. However, we can observe that the form of the subterms impose constraints on the types. We can write down these constraints and then try to solve them. Suppose we want to infer the type of a given λ-term e. Without loss of generality, suppose we have α- converted e so that no variable is bound more than once and no variable with a binding occurrence λx also occurs free. 1 Let e 1,..., e m be an enumeration of all occurrences of subterms of e. We first assign a unique type variable α i to each e i, 1 i m, as well as a unique type variable β x to each variable x. Then we take the following constraints: if e i is an occurrence of a variable x, the constraint α i = β x ; if e i is an occurrence of an application e j e k, the constraint α j = α k α i ; and if e i is an occurrence of an abstraction λx. e j, the constraint α i = β x α j. This gives us a list of pairs (σ, τ) of type expressions representing type constraints σ = τ imposed by the typing rules above. Now we do unification on the constraints and apply the resulting substitution to the type variable α e. The result is the mgu of e. 4.1 An Example Here is an example of the algorithm applied to the combinator S = λxyz. xz(yz). Let us mark the second occurrence of z as z to distinguish it from the first occurrence, although they are occurrences of the same variable z. Each occurrence of a subterm generates a constraint: e 1 = λx. λy. λz. xz(yz ) α 1 = β x α 2 e 2 = λy. λz. xz(yz ) α 2 = β y α 3 e 3 = λz. xz(yz ) α 3 = β z α 4 e 4 = xz(yz ) α 5 = α 8 α 4 e 5 = xz α 6 = α 7 α 5 e 6 = x α 6 = β x e 7 = z α 7 = β z e 8 = yz α 9 = α 10 α 8 e 9 = y α 9 = β y e 10 = z α 10 = β z. 1 This assumption is known as the Barendregt variable convention after Henk Barendregt. 4

Solving these constraints using Robinson s algorithm yields α 1 = (α 7 α 8 α 4 ) (α 7 α 8 ) α 7 α 4 α 2 = (α 7 α 8 ) α 7 α 4 α 3 = α 7 α 4 α 5 = α 8 α 4 α 6 = α 7 α 8 α 4 α 9 = α 7 α 8 α 10 = α 7 β x = α 7 α 8 α 4 β y = α 7 α 8 β z = α 7 so we see that the most general type of e 1 is (α 7 α 8 α 4 ) (α 7 α 8 ) α 7 α 4. 5