Type Inference David Walker COS 320. Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs useful.

Slides:



Advertisements
Similar presentations
Types and Programming Languages Lecture 13 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Advertisements

Types and Programming Languages Lecture 15 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Types and Programming Languages Lecture 7 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Functional Programming Lecture 10 - type checking.
Substitution & Evaluation Order cos 441 David Walker.
More ML Compiling Techniques David Walker. Today More data structures lists More functions More modules.
Chapter 6 Intermediate Code Generation
Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists Dan Grossman Winter 2013.
1 PROPERTIES OF A TYPE ABSTRACT INTERPRETATER. 2 MOTIVATION OF THE EXPERIMENT § a well understood case l type inference in functional programming à la.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Type checking © Marcelo d’Amorim 2010.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
INF 212 ANALYSIS OF PROG. LANGS Type Systems Instructors: Crista Lopes Copyright © Instructors.
ISBN Chapter 3 Describing Syntax and Semantics.
CS 611 Advanced Programming Languages Andrew Myers Cornell University Lecture 27 Type inference 2 Nov 05.
Constraint Logic Programming Ryan Kinworthy. Overview Introduction Logic Programming LP as a constraint programming language Constraint Logic Programming.
1 Constraint Programming Maurizio Gabbrielli Universita’ di Bologna Slides by: K. Marriott.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Catriel Beeri Pls/Winter 2004/5 type reconstruction 1 Type Reconstruction & Parametric Polymorphism  Introduction  Unification and type reconstruction.
Type Inference David Walker COS 441. Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs useful.
Type Inference David Walker CS 510, Fall Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs.
Type Inference II David Walker COS 441. Type Inference Goal: Given unannotated program, find its type or report it does not type check Overview: generate.
Semantics for MinML COS 441 Princeton University Fall 2004.
Describing Syntax and Semantics
Type Inference: CIS Seminar, 11/3/2009 Type inference: Inside the Type Checker. A presentation by: Daniel Tuck.
Introduction Even though the syntax of Scheme is simple, it can be very difficult to determine the semantics of an expression. Hacker’s approach: Run it.
Type Inference II David Walker CS 510. ML-style Polymorphism 2 characteristics: prenex (let) polymorphism let f : all [a,b,c].t =... in e polymorphic.
CSE341: Programming Languages Lecture 11 Type Inference Dan Grossman Winter 2013.
Step 1: Simplify Both Sides, if possible Distribute Combine like terms Step 2: Move the variable to one side Add or Subtract Like Term Step 3: Solve for.
Type Systems CS Definitions Program analysis Discovering facts about programs. Dynamic analysis Program analysis by using program executions.
Type Safety Kangwon National University 임현승 Programming Languages.
Type Inference II David Walker COS 441. Type Inference Goal: Given unannotated program, find its type or report it does not type check Overview: generate.
Chapter 9: Functional Programming in a Typed Language.
Section 2.2 More about Solving Equations. Objectives Use more than one property of equality to solve equations. Simplify expressions to solve equations.
Ch 2.5 Variable on Both Sides Objective: To solve equations where one variable exists on both sides of the equation.
Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L06-1 September 26, 2006http:// Type Inference September.
12/9/20151 Programming Languages and Compilers (CS 421) Elsa L Gunter 2112 SC, UIUC Based in part on slides by Mattox.
1.6. DEFINITIONS  An equation is a statement that two expressions are equal.  Usually contains 1 or more variables  A variable is a symbol that represents.
CS412/413 Introduction to Compilers Radu Rugina Lecture 13 : Static Semantics 18 Feb 02.
COMP 412, FALL Type Systems II C OMP 412 Rice University Houston, Texas Fall 2000 Copyright 2000, Robert Cartwright, all rights reserved. Students.
Types and Programming Languages Lecture 14 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Type checking and inference Question 2: Typing the application (if #t (+ 1 2) 3) STAGE-I: Renaming ExpressionVariable (if #t (+ 1 2) 3) T0 (+ 1 2) T1 +
1 Proving Properties of Recursive List Functions CS 270 Math Foundations of CS Jeremy Johnson.
COMP 412, FALL Type Systems C OMP 412 Rice University Houston, Texas Fall 2000 Copyright 2000, Robert Cartwright, all rights reserved. Students.
Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L05-1 September 21, 2006http:// Types and Simple Type.
Lesson 10 Type Reconstruction
CS5205: Foundation in Programming Languages Type Reconstruction
Functional Programming
Programming Languages and Compilers (CS 421)
CSE341: Programming Languages Lecture 11 Type Inference
Lesson #6 Modular Programming and Functions.
ML: a quasi-functional language with strong typing
Introduction to Parsing (adapted from CS 164 at Berkeley)
Example: Solve the equation. Multiply both sides by 5. Simplify both sides. Add –3y to both sides. Simplify both sides. Add –30 to both sides. Simplify.
Lesson #6 Modular Programming and Functions.
Programming Languages and Compilers (CS 421)
Lesson #6 Modular Programming and Functions.
Typed Arithmetic Expressions
FP Foundations, Scheme In Text: Chapter 14.
Objective Solve equations in one variable that contain variable terms on both sides.
CSE341: Programming Languages Lecture 11 Type Inference
CSE341: Programming Languages Lecture 11 Type Inference
Lesson #6 Modular Programming and Functions.
Objective Solve equations in one variable that contain variable terms on both sides.
CSE341: Programming Languages Lecture 11 Type Inference
Algebra 1 09/21/16 EQ: How do I solve equations with variables on both sides? HW: Due Friday pg. 95 # 1-33 all Bring textbooks tomorrow Quiz on Friday.
Lesson Objective: I will be able to …
CSE341: Programming Languages Lecture 11 Type Inference
CSE341: Programming Languages Lecture 11 Type Inference
Presentation transcript:

Type Inference David Walker COS 320

Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs useful in more contexts universal polymorphism => code reuse modules & abstract types => code reuse subtyping => code reuse Types clutter programs and slow down programmer productivity type inference uninformative annotations may be omitted

Type Inference overview generation of type constraints from unannotated simply-typed programs Fun has subtyping and still needed some annotations There is an algorithm for complete type inference for MinML without subtyping (and of course for full ML, including parametric polymorphism) solving type constraints

Type Schemes A type scheme contains type variables (a, b, c) that may be filled in during type inference s ::= a | int | bool | s1 -> s2 A term scheme is a term that contains type schemes rather than proper types e ::=... | fun f (x:s1) : s2 = e

Example fun map (f, l) = if null (l) then nil else cons (f (hd l), map (f, tl l)))

Step 1: Add Type Schemes fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l), map (f, tl l))) type schemes on functions

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l), map (f, tl l))) for each expression, perform type inference on sub expressions, assigning them type schemes and generating constraints that must be solved

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l), map (f, tl l))) begin with the if expression & recursively perform type inference on its subexpressions

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l), map (f, tl l))) b = b’ list since argument to null must be a list

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l), map (f, tl l))) : d list since nil is some kind of list constraints b = b’ list

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l), map (f, tl l))) : d list constraints b = b’ list b = b’’ list b = b’’’ list since hd and tl are functions that take list arguments

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l : b’’ ), map (f, tl l : b’’’ list ))) : d list constraints b = b’ list b = b’’ list b = b’’’ list a = a

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l : b’’ ) : a’, map (f, tl l) : c )) : d list constraints b = b’ list b = b’’ list b = b’’’ list a = a b = b’’’ list a = b’’ -> a’

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l : b’’ ) : a’, map (f, tl l) : c )) : c’ list : d list constraints b = b’ list b = b’’ list b = b’’’ list a = a b = b’’’ list a = b’’ -> a’ c = c’ list a’ = c’

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l : b’’ ) : a’, map (f, tl l) : c )) : c’ list : d list constraints b = b’ list b = b’’ list b = b’’’ list a = a b = b’’’ list a = b’’ -> a’ c = c’ list a’ = c’ d list = c’ list

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l : b’’ ) : a’, map (f, tl l) : c )) : c’ list : d list constraints b = b’ list b = b’’ list b = b’’’ list a = a b = b’’’ list a = b’’ -> a’ c = c’ list a’ = c’ d list = c’ list d list = c

Step 2: Generate Constraints fun map (f : a, l : b) : c = if null (l) then nil else cons (f (hd l), map (f, tl l))) final constraints b = b’ list b = b’’ list b = b’’’ list a = a b = b’’’ list a = b’’ -> a’ c = c’ list a’ = c’ d list = c’ list d list = c

Step 3: Solve Constraints final constraints b = b’ list b = b’’ list b = b’’’ list a = a... Constraint solution provides all possible solutions to type scheme annotations on terms solution a = b’ -> c’ b = b’ list c = c’ list map (f : a -> b x : a list) : b list =...

Step 4: Generate types Generate types from type schemes Option 1: pick an instance of the most general type when we have completed type inference on the entire program map : (int -> int) -> int list -> int list Option 2: generate polymorphic types for program parts and continue (polymorphic) type inference map : ForAll (a,b,c) (a -> b) -> a list -> b list

Type Inference Details Type constraints q are sets of equations between type schemes q ::= {s11 = s12,..., sn1 = sn2} eg: {b = b’ list, a = b -> c}

Constraint Generation Syntax-directed constraint generation our algorithm crawls over abstract syntax of untyped expressions and generates a term scheme a set of constraints Algorithm defined as set of inference rules programming notation: tc(G, u) = (e, t, q) math notation: G |-- u => e : t, q inputs outputs

Constraint Generation G |-- x ==> x : G |-- 3 ==> 3 : G |-- true ==> true : G |-- false ==> false :

Constraint Generation G |-- x ==> x : s, { } (if G(x) = s) G |-- 3 ==> 3 : G |-- true ==> true : G |-- false ==> false :

Constraint Generation G |-- x ==> x : s, { } (if G(x) = s) G |-- 3 ==> 3 : int, { } G |-- true ==> true : G |-- false ==> false :

Constraint Generation G |-- x ==> x : s, { } (if G(x) = s) G |-- 3 ==> 3 : int, { } G |-- true ==> true : bool, { } G |-- false ==> false : bool, { }

Operators G |-- u1 + u2 ==>

Operators G |-- u1 ==> G |-- u2 ==> G |-- u1 + u2 ==>

Operators G |-- u1 ==> e1 G |-- u2 ==> e G |-- u1 + u2 ==>

Operators G |-- u1 ==> e1 G |-- u2 ==> e G |-- u1 + u2 ==> e1 + e2

Operators G |-- u1 ==> e1 G |-- u2 ==> e G |-- u1 + u2 ==> e1 + e2 : int

Operators G |-- u1 ==> e1 : t1, q1G |-- u2 ==> e2 : G |-- u1 + u2 ==> e1 + e2 : int, q1 U {t1 = int}

Operators G |-- u1 ==> e1 : t1, q1G |-- u2 ==> e2 : t2, q G |-- u1 + u2 ==> e1 + e2 : int, q1 U q2 U {t1 = int, t2 = int}

Operators G |-- u1

Operators G |-- u1 ==> e1 : t1, q1G |-- u2 ==> e2 : t2, q G |-- u1 e1 < e2 : bool,

Operators G |-- u1 ==> e1 : t1, q1G |-- u2 ==> e2 : t2, q G |-- u1 e1 < e2 : bool,

Operators G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q G |-- u1 e1 + e2 : bool, q1 U q2 U {t1 = int, t2 = int}

If statements G |-- if u1 then u2 else u3 ==>

If statements G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q2 G |-- u3 ==> e3 : t3, q G |-- if u1 then u2 else u3 ==> if e1 then e2 else e3 :

If statements G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q2 G |-- u3 ==> e3 : t3, q G |-- if u1 then u2 else u3 ==> if e1 then e2 else e3 : a, q1 U q2 U q3 U {t1 = bool, a = t2, a = t3}

Function Application G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q G |-- u1 u2==> e1 e2 : a, q1 U q2 U {t1 = t2 -> a}

Function Application G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q G |-- u1 u2==> e1 e2 : a,

Function Declaration G, f : a -> b, x : a |-- u ==> e : t, q G |-- fun f(x) is u end ==> fun f (x : a) : b is e end : a -> b, q U {t = b}

Function Declaration G, f : a -> b, x : a |-- u ==> e : t, q G |-- fun f(x) = u ==> fun f (x : a) : b = e :

Solving Constraints A solution to a system of type constraints is a substitution S a function from type variables to type schemes, eg: S(a) = a S(b) = int S(c) = a -> a

Substitutions Applying a substitution S: substitute(S,int) = int substitute(S,s1 -> s2) = substitute(s1) -> substitute(s2) substitute(S,a) = s (if S(a) = s) Due to laziness, I will write S(s) instead of substitute(S, s)

Unification Unification: An algorithm that provides the principal solution to a set of constraints (if one exists) Unification systematically simplifies a set of constraints, yielding a substitution Starting state of unification process: (Id,q) Final state of unification process: (S, { })

Unification Machine We can specify unification as a rewriting system: Given (S, q), systematically pick a constraint from q and simplify it, possibly adding to the substitution Use inductive definitions to specify rewriting. Judgment form: (S,q) -> (S’,q’)

Unification Machine Base types & simple variables: (S,{int=int} U q) -> ???

Unification Machine Base types & simple variables: (S,{int=int} U q) -> (S, q)

Unification Machine Base types & simple variables: (S,{int=int} U q) -> (S, q) (S,{bool=bool} U q) -> ??? (S,{a=a} U q) -> ???

Unification Machine Base types & simple variables: (S,{int=int} U q) -> (S, q) (S,{bool=bool} U q) -> (S, q) (S,{a=a} U q) -> (S, q)

Unification Machine Variable definitions (a not in s) (S,{a=s} U q) -> (S[a=s], [s/a]q) (a not in s) (S,{s=a} U q) -> (S[a=s], [s/a]q)

Unification Machine Functions: (S,{s11 -> s12= s21 -> s22} U q) -> ???

Unification Machine Functions: (S,{s11 -> s12= s21 -> s22} U q) -> (S, {s11 = s21, s12 = s22} U q)

Occurs Check What is the solution to {a = a -> a}?

Occurs Check What is the solution to {a = a -> a}? There is none! The occurs check detects this situation (a not in s) (S,{s=a} U q) -> (S[a=s], [s/a]q) occurs check

Unification Machine Gets Stuck Recall: final states have the form (S, { }) Stuck states (S,q) are such that every equation in q has the form: int = bool s1 -> s2 = s (s not function type) a = s (s contains a) or is symmetric to one of the above Stuck states arise when constraints are unsolvable

Termination We want unification to terminate (to give us a type reconstruction algorithm) In other words, we want to show that there is no infinite sequence of states (S1,q1) -> (S2,q2) ->...

Termination We associate an ordering with constraints q < q’ if and only if q contains fewer variables than q’ q contains the same number of variables as q’ but fewer type constructors (ie: fewer occurrences of int, bool, or “->”) This is a lexicographic ordering we can prove (by contradiction) that there is no infinite decreasing sequence of constraints

Termination Lemma: Every step reduces the size of q Proof: Examine each case of the definition of the reduction relation & show that our metric goes down (S,{int=int} U q) -> (S, q) (S,{bool=bool} U q) -> (S, q) (S,{a=a} U q) -> (S, q) (S,{s11 -> s12= s21 -> s22} U q) -> (S, {s11 = s21, s12 = s22} U q) (a not in FV(s)) (S,{a=s} U q) -> (S[a=s], [s/a]q)

Properties of Solutions given any set of constraints q, our unification machine reduces (Id, q) to (S, { }) such that S(q) is a set of true equations (eg, int = int, bool -> a = bool -> a, etc) S is a principal solution to the constraints. it generates more general types than any other substitution T: ie: a -> a is more general than int -> int ie: T replaces more type variables with more specific types

Summary: Type Inference Type inference algorithm. Given a context G, and untyped term u: Find e, t, q such that G |- u ==> e : t, q Find principal solution S of q via unification if no solution exists, there is no way to type check the term Apply S to e, ie our solution is S(e) S(e) contains schematic type variables a,b,c, etc that may be instantiated with any type Since S is principal, S(e) characterizes all possible typings of e

Compare with Subtyping Algorithm Simple type inference algorithm. Given a context G (mapping variables to type schemes), and untyped term u: Find e, t, q such that G |- u ==> e : t, q Type equations collected on the side Subtyping algorithm given a context G (mapping variables to full types) Find t such that G |-- e : t Subtyping equations solved when they are generated Lots of current research on type inference that combines subtyping and polymorphic type reconstruction for advanced type systems