Types and Programming Languages Lecture 14 Simon Gay Department of Computing Science University of Glasgow 2006/07.

Slides:



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

Types and Programming Languages Lecture 13 Simon Gay Department of Computing Science University of Glasgow 2006/07.
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.
Type Inference David Walker COS 320. Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs useful.
Introduction to Recursion and Recursive Algorithms
Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
Semantics Static semantics Dynamic semantics attribute grammars
Letrec fact(n) = if zero?(n) then 1 else *(n, (fact sub1(n))) 4.4 Type Inference Type declarations aren't always necessary. In our toy typed language,
Cs776 (Prasad)L4Poly1 Polymorphic Type System. cs776 (Prasad)L4Poly2 Goals Allow expression of “for all types T” fun I x = x I : ’a -> ’a Allow expression.
1 PROPERTIES OF A TYPE ABSTRACT INTERPRETATER. 2 MOTIVATION OF THE EXPERIMENT § a well understood case l type inference in functional programming à la.
Rigorous Software Development CSCI-GA Instructor: Thomas Wies Spring 2012 Lecture 11.
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 =
CSE-321 Programming Languages Predicative Polymorphic -Calculus POSTECH May 23, 2007 박성우.
INF 212 ANALYSIS OF PROG. LANGS Type Systems Instructors: Crista Lopes Copyright © Instructors.
Catriel Beeri Pls/Winter 2004/5 last 55 Two comments on let polymorphism I. What is the (time, space) complexity of type reconstruction? In practice –
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.
Program Design and Development
Introduction to ML - Part 2 Kenny Zhu. What is next? ML has a rich set of structured values Tuples: (17, true, “stuff”) Records: {name = “george”, age.
1 Chapter 1: Constraints What are they, what do they do and what can I use them for.
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.
Type Inference: CIS Seminar, 11/3/2009 Type inference: Inside the Type Checker. A presentation by: Daniel Tuck.
Linear Systems The definition of a linear equation given in Chapter 1 can be extended to more variables; any equation of the form for real numbers.
SOLVING SYSTEMS USING SUBSTITUTION
CSE341: Programming Languages Lecture 11 Type Inference Dan Grossman Winter 2013.
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Computer Science Department Data Structure & Algorithms Lecture 8 Recursion.
Typed Lambda Calculus Chapter 9 Benjamin Pierce Types and Programming Languages.
CS Describing Syntax CS 3360 Spring 2012 Sec Adapted from Addison Wesley’s lecture notes (Copyright © 2004 Pearson Addison Wesley)
Goal: Solve a system of linear equations in two variables by the linear combination method.
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.
# ACS 168 Structured Programming Using the Computer Chapter 2 Spring 2002 Prepared by Shirley White.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
© Kenneth C. Louden, Chapter 11 - Functional Programming, Part III: Theory Programming Languages: Principles and Practice, 2nd Ed. Kenneth C. Louden.
Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L06-1 September 26, 2006http:// Type Inference September.
Examples of the Unification Algorithm { X = int, Y = X  X } unify({ X = int, Y = X  X }) S=X, T=int, C’={Y = X  X} = [ X  int ] ; unify({ Y = int 
Chapter 3 Part II Describing Syntax and Semantics.
Types and Programming Languages Lecture 6 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Ch. 13 Ch. 131 jcmt CSE 3302 Programming Languages CSE3302 Programming Languages (notes?) Dr. Carter Tiernan.
Data Structures & Algorithms
Types and Programming Languages Lecture 12 Simon Gay Department of Computing Science University of Glasgow 2006/07.
12/9/20151 Programming Languages and Compilers (CS 421) Elsa L Gunter 2112 SC, UIUC Based in part on slides by Mattox.
Function Definition by Cases and Recursion Lecture 2, Programmeringsteknik del A.
Advanced Formal Methods Lecture 3: Simply Typed Lambda calculus Mads Dam KTH/CSC Course 2D1453, Some material from B. Pierce: TAPL + some from.
Types and Programming Languages Lecture 11 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Principle of Programming Lanugages 3: Compilation of statements Statements in C Assertion Hoare logic Department of Information Science and Engineering.
Advanced Functional Programming Tim Sheard 1 Lecture 17 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture:
Types and Programming Languages
COMP 412, FALL Type Systems II C OMP 412 Rice University Houston, Texas Fall 2000 Copyright 2000, Robert Cartwright, all rights reserved. Students.
CMSC 330: Organization of Programming Languages Operational Semantics.
Types and Programming Languages Lecture 10 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Types and Programming Languages Lecture 3 Simon Gay Department of Computing Science University of Glasgow 2006/07.
4 - Conditional Control Structures CHAPTER 4. Introduction A Program is usually not limited to a linear sequence of instructions. In real life, a programme.
Dr. Philip Cannata 1 Programming Languages Chapters 24 – 29 Types, Type Judgments, Type Systems and Type Safety - Chapters Explicit Polymorphism.
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.
1 Chapter 1: Constraints What are they, what do they do and what can I use them for.
Lesson 10 Type Reconstruction
CS5205: Foundation in Programming Languages Type Reconstruction
What are they, what do they do and what can I use them for.
Programming Languages and Compilers (CS 421)
CSE-321 Programming Languages Simply Typed -Calculus
SYSTEMS OF LINEAR EQUATIONS
Presentation transcript:

Types and Programming Languages Lecture 14 Simon Gay Department of Computing Science University of Glasgow 2006/07

Types and Programming Languages Lecture 14 - Simon Gay2 Unification We now need to see how to solve sets of constraints. We use the unification algorithm, which, given a set of constraints, checks that there is a solution and if so finds the “best” one (in the sense that all other solutions can be generated from it). Unification has more general applications: notably it is the basis of logic programming as found in languages such as Prolog.

2006/07Types and Programming Languages Lecture 14 - Simon Gay3 Principal Unifiers Definition: a substitution  is more general (or less specific) than a substitution  ’, written    ’, if  ’ =  ;  for some substitution . Example: [ X  Y  int ] is more general than [ X  bool  int ] because [ X  bool  int ] = [ X  Y  int ] ; [ Y  bool ]. Definition: a principal unifier (or most general unifier) for a constraint set C is a substitution  that satisfies C and such that    ’ for every substitution  ’ satisfying C. The unification algorithm finds a principal unifier, if it exists, for a set of constraints.

2006/07Types and Programming Languages Lecture 14 - Simon Gay4 Exercises: Principal Unifiers Find a principal unifier (or explain why it doesn’t exist) for each of the following constraint sets. 1.{ X = int, Y = X  X } 2.{ int  int = X  Y } 3.{ X  Y = Y  Z, Z = U  W } 4.{ int = int  Y } 5.{ Y = int  Y } 6.{ } (the empty set of constraints)

2006/07Types and Programming Languages Lecture 14 - Simon Gay5 The Unification Algorithm unify(C) = if C = { } then [ ] else let { S = T }  C’ = C in if S = T then unify(C’) else if S = X and X  FV(T) then [ X  T ] ; unify(C’ [ X  T ] ) else if T = X and X  FV(S) then [ X  S ] ; unify(C’ [ X  S ] ) else if S = A  B and T = A’  B’ then unify(C’  {A = A’, B = B’}) else fail Given a constraint set C, return a substitution.

2006/07Types and Programming Languages Lecture 14 - Simon Gay6 Notes on the Unification Algorithm The phrase “let { S = T }  C’ = C ” means “choose a constraint S = T from the set C and let C’ denote the remaining constraints from C. X stands for any type variable. FV(T) means all of the type variables occurring in T. The conditions X  FV(T) and X  FV(S) are the “occurs check”. They prevent the algorithm from generating cyclic substitutions such as [ X  X  X ] which do not make sense if we are working with finite type expressions. (They would make sense in a language with recursive types, and then the occurs checks can be omitted.)

2006/07Types and Programming Languages Lecture 14 - Simon Gay7 Correctness of the Unification Algorithm It is possible to prove: 1.unify(C) halts, either by failing or by returning a substitution, for all constraint sets C. 2.if unify(C) =  then  is a principal unifier for C.

2006/07Types and Programming Languages Lecture 14 - Simon Gay8 Examples of the Unification Algorithm { X = int, Y = X  X } unify({ X = int, Y = X  X }) S=X, T=int, C’={Y = X  X} = [ X  int ] ; unify({ Y = int  int }) S=Y, T=int  int, C’={ } = [ X  int ] ; [ Y  int  int ] ; unify({ }) = [ X  int ] ; [ Y  int  int ] ; [ ] = [ X  int, Y  int  int ] { int  int = X  Y } unify({ int  int = X  Y }) S=int  int, T=X  Y, C’={ } = unify({ int = X, int = Y }) S=int, T=X, C’={ int = Y } = [ X  int ] ; unify({ int = Y }) S=int, T=Y, C’={ } = [ X  int ] ; [ Y  int ] ; unify({ }) = [ X  int, Y  int ]

2006/07Types and Programming Languages Lecture 14 - Simon Gay9 Examples of the Unification Algorithm { X  Y = Y  Z, Z = U  W } unify({ X  Y = Y  Z, Z = U  W }) S=X  Y, T= Y  Z, C’={Z = U  W} = unify({ Z = U  W, X = Y, Y = Z }) S=Z, T=U  W, C’={ X = Y, Y = Z } = [ Z  U  W ] ; unify({ X = Y, Y = U  W }) = [ Z  U  W ] ; [ X  Y ] ; unify({ Y = U  W }) = [ Z  U  W ] ; [ X  Y ] ; [ Y  U  W ] = [ Z  U  W, X  Y ] ; [ Y  U  W ] = [ Z  U  W, X  U  W, Y  U  W ]

2006/07Types and Programming Languages Lecture 14 - Simon Gay10 Examples of the Unification Algorithm { int = int  Y } unify({ int = int  Y }) S=int, T= int  Y, C’={ } fails because no cases match { Y = int  Y } unify({ Y = int  Y }) S=Y, T= int  Y, C’={ } fails because no cases match, due to the occurs check { } unify({ }) = [ ]

2006/07Types and Programming Languages Lecture 14 - Simon Gay11 Principal Types Definition: A principal solution for ( ,t,S,C) is a solution ( ,T) such that whenever (  ’,T’) is also a solution for ( ,t,S,C) we have    ’. When ( ,T) is a principal solution, we call T a principal type of t under . Theorem: If ( ,t,S,C) has any solution then it has a principal solution. The unification algorithm can be used to determine whether ( ,t,S,C) has a solution and, if so, to calculate a principal solution.

2006/07Types and Programming Languages Lecture 14 - Simon Gay12 Implicit Type Annotations Languages supporting type reconstruction (for example, ML) give the programmer the option of omitting type annotations on lambda-abstractions. One way to achieve this is to make the parser fill in omitted annotations with fresh type variables. A better approach is to add un-annotated abstractions to the syntax of terms, and add a rule to the constraint typing relation: (CT-AbsInf) where X is a fresh type variable. This allows (requires) a different type variable to be chosen for every occurrence of this abstraction. This will be important in a moment...

2006/07Types and Programming Languages Lecture 14 - Simon Gay13 Type Reconstruction is not Polymorphism Consider the function double, and an example use: let double = f:int  int. a:int. f(f(a)) in double ( x:int. x+2) 2 end Alternatively we can define double so that it can be used to double a boolean function: let double = f:bool  bool. a:bool. f(f(a)) in double ( x:bool. x) false end

2006/07Types and Programming Languages Lecture 14 - Simon Gay14 Type Reconstruction is not Polymorphism To use both double functions in the same program, we must define two versions: let double_int = f:int  int. a:int. f(f(a)) double_bool = f:bool  bool. a:bool. f(f(a)) in let a = double_int ( x:int. x+2) 2 let b = double_bool ( x:bool. x) false end

2006/07Types and Programming Languages Lecture 14 - Simon Gay15 Type Reconstruction is not Polymorphism Annotating the abstractions in double with a type variable does not help: let double = f:X  X. a:X. f(f(a)) in let a = double ( x:int. x+2) 2 let b = double ( x:bool. x) false end because the use of double in the definition of a generates the constraint X  X = int  int and the use of double in the definition of b generates the constraint X  X = bool  bool. These constraints cannot both be satisfied, so the program is untypable.

2006/07Types and Programming Languages Lecture 14 - Simon Gay16 Let-Polymorphism We need to associate a different type variable with each use of double. Change the typing rule for let from this: (T-Let) to this: (T-LetPoly) and in the constraint typing system we get this: (CT-LetPoly)

2006/07Types and Programming Languages Lecture 14 - Simon Gay17 Let-Polymorphism In effect we have changed the typing rules for let so that they do a reduction step before calculating types: let x = v in e  e[v/x] Also we need to rewrite the definition of double to use implicit annotations on the abstractions (rule CT-AbsInf): let double = f. a. f(f(a)) in let a = double ( x:int. x+2) 2 let b = double ( x:bool. x) false end Now this program is typable, because rule CT-LetPoly creates two copies of double, and rule CT-AbsInf assigns a different type variable to each one.

2006/07Types and Programming Languages Lecture 14 - Simon Gay18 Let-Polymorphism in Practice An obvious problem with the typing rule (T-LetPoly) is that if x does not occur in e’ then e is never typechecked! Change the rules to (T-LetPoly) (CT-LetPoly)

2006/07Types and Programming Languages Lecture 14 - Simon Gay19 Let-Polymorphism in Practice If x occurs several times in e’ then e will be typechecked several times. Instead, a practical implementation would typecheck let x = e in e’ in an environment  as follows. 1.Use the constraint typing rules to calculate a type S and a set of constraints C for e. 2.Use unification to obtain the principal type of e, T. 3.Generalize any type variables in T, as long as they do not occur in . If these variables are X, Y,..., Z then the principal type scheme of e is  X,Y,...,Z.T 4.Put x into the environment with its principal type scheme. Start typechecking e’. 5.When x is encountered in e’, instantiate its type scheme with fresh type variables.

2006/07Types and Programming Languages Lecture 14 - Simon Gay20 Polymorphism and References Combining polymorphism and references can cause problems. Example: let r = ref ( x.x) in r := x:int. x+1 ; (!r)true end x.x has principal type X  X so ref ( x.x) has principal type Ref(X  X) and because X occurs nowhere else we generalize to the type scheme  X. Ref(X  X) and put r into the environment with this type scheme.

2006/07Types and Programming Languages Lecture 14 - Simon Gay21 Polymorphism and References When typechecking r := x:int. x+1 ; (!r)true we instantiate the type scheme with a new type variable for each occurrence of r. So r := x:int. x+1 is typechecked with r:Ref(Y  Y) and (!r)true is typechecked with r:Ref(Z  Z). Solving the constraints results in a successful typecheck with Y = int and Z = bool. But this is clearly unsafe: executing this code results in applying x:int. x+1 to true. What has gone wrong? The typing rules allocate two type variables, one for each occurrence of r, but at runtime only one location is actually allocated.

2006/07Types and Programming Languages Lecture 14 - Simon Gay22 Polymorphism and References The solution to this problem is the value restriction: only generalize the type of a let-binding if its right hand side is a syntactic value. In this example, ref ( x.x) is not a value because it reduces to a new location m. So it is not valid to generalize the type of r. It is just X  X and the same X is used when typechecking both r := x:int. x+1 and (!r)true. The assignment introduces the constraint X = int which means that (!r)true is a type error. It turns out that in practice the value restriction makes very little difference to programming.

2006/07Types and Programming Languages Lecture 14 - Simon Gay23 Example of the Value Restriction In ML, the following code generates a type error because of the value restriction. let f = x. y.x(y) in let g = f ( x.x) in...g(1)...g(true)... end In practice hardly any programs use this style of coding.

2006/07Types and Programming Languages Lecture 14 - Simon Gay24 Algorithmic Issues Generalizing principal types to type schemes eliminates the inefficiency of substituting while typechecking let expressions. In practice, typechecking with let-polymorphism seems to be very efficient: “essentially linear” in the size of the term. The worst-case complexity is exponential, for example: let a = x.(x,x) in let b = x.a(a(x)) in let c = x.b(b(x)) in let d = x.c(c(x)) in let e = x.d(d(x)) in let f = x.e(e(x)) in f( x.x)

2006/07Types and Programming Languages Lecture 14 - Simon Gay25 Let-Polymorphism in Practice Let-polymorphism, with its principal type schemes, supports generic data structures and algorithms very nicely, especially when the language allows polymorphic type constructors to be defined. This is familiar from Haskell. Example: Define a polymorphic type constructor Hashtable, and functions with principal type schemes like get :  X. Hashtable X  string  X In a practical language the  is likely to be omitted, for example in ML: get : ’a Hashtable  string  ’a Implicitly all type variables are generalized at the top level.