type inference n.
Download
Skip this Video
Download Presentation
Type Inference

Loading in 2 Seconds...

play fullscreen
1 / 63

Type Inference - PowerPoint PPT Presentation


  • 142 Views
  • Uploaded on

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

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Type Inference' - yama


Download Now An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
type inference

Type Inference

David Walker

COS 320

criticisms of typed languages
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 inference1
Type Inference
  • 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
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
Example

fun map (f, l) =

if null (l) then

nil

else

cons (f (hd l), map (f, tl l)))

step 1 add type schemes
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
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 constraints1
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 constraints2
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 constraints3
Step 2: Generate Constraints

constraints

b = b’ list

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

step 2 generate constraints4
Step 2: Generate Constraints

constraints

b = b’ list

fun map (f : a, l : b) : c =

if null (l) then

nil

else

cons (f (hd l), map (f, tl l)))

: d list

b = b’’’ list

b = b’’ list

since hd and tl are functions that take list arguments

step 2 generate constraints5
Step 2: Generate Constraints

constraints

b = b’ list

b = b’’ list

b = b’’’ list

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

a = a

b = b’’’ list

step 2 generate constraints6
Step 2: Generate Constraints

constraints

b = b’ list

b = b’’ list

b = b’’’ list

a = a

b = b’’’ list

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

a = b’’ -> a’

step 2 generate constraints7
Step 2: Generate Constraints

constraints

b = b’ list

b = b’’ list

b = b’’’ list

a = a

b = b’’’ list

a = b’’ -> a’

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

c = c’ list

a’ = c’

step 2 generate constraints8
Step 2: Generate Constraints

constraints

b = b’ list

b = b’’ list

b = b’’’ list

a = a

b = b’’’ list

a = b’’ -> a’

c = c’ list

a’ = c’

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

d list = c’ list

step 2 generate constraints9
Step 2: Generate Constraints

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

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

: d list

d list = c

step 2 generate constraints10
Step 2: Generate Constraints

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

fun map (f : a, l : b) : c =

if null (l) then

nil

else

cons (f (hd l), map (f, tl l)))

step 3 solve constraints
Step 3: Solve Constraints
  • Constraint solution provides all possible solutions to type scheme annotations on terms

final

constraints

b = b’ list

b = b’’ list

b = b’’’ list

a = a

...

map (f : a -> b

x : a list)

: b list =

...

solution

a = b’ -> c’

b = b’ list

c = c’ list

step 4 generate types
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 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
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

outputs

inputs

constraint generation1
Constraint Generation

G |-- x ==> x :

G |-- 3 ==> 3 :

G |-- true ==> true :

G |-- false ==> false :

constraint generation2
Constraint Generation

G |-- x ==> x : s, { } (if G(x) = s)

G |-- 3 ==> 3 :

G |-- true ==> true :

G |-- false ==> false :

constraint generation3
Constraint Generation

G |-- x ==> x : s, { } (if G(x) = s)

G |-- 3 ==> 3 : int, { }

G |-- true ==> true :

G |-- false ==> false :

constraint generation4
Constraint Generation

G |-- x ==> x : s, { } (if G(x) = s)

G |-- 3 ==> 3 : int, { }

G |-- true ==> true : bool, { }

G |-- false ==> false : bool, { }

operators
Operators

------------------------------------------------------------------------

G |-- u1 + u2 ==>

operators1
Operators

G |-- u1 ==> G |-- u2 ==>

------------------------------------------------------------------------

G |-- u1 + u2 ==>

operators2
Operators

G |-- u1 ==> e1 G |-- u2 ==> e2

------------------------------------------------------------------------

G |-- u1 + u2 ==>

operators3
Operators

G |-- u1 ==> e1 G |-- u2 ==> e2

------------------------------------------------------------------------

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

operators4
Operators

G |-- u1 ==> e1 G |-- u2 ==> e2

------------------------------------------------------------------------

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

operators5
Operators

G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 :

------------------------------------------------------------------------

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

operators6
Operators

G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q2

------------------------------------------------------------------------

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

operators7
Operators

------------------------------------------------------------------------

G |-- u1 < u2 ==>

operators8
Operators

G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q2

------------------------------------------------------------------------

G |-- u1 < u2 ==> e1 < e2 : bool,

operators9
Operators

G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q2

------------------------------------------------------------------------

G |-- u1 < u2 ==> e1 < e2 : bool,

operators10
Operators

G |-- u1 ==> e1 : t1, q1 G |-- u2 ==> e2 : t2, q2

------------------------------------------------------------------------

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

if statements
If statements

----------------------------------------------------------------

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

if statements1
If statements

G |-- u1 ==> e1 : t1, q1

G |-- u2 ==> e2 : t2, q2

G |-- u3 ==> e3 : t3, q3

----------------------------------------------------------------

G |-- if u1 then u2 else u3 ==> if e1 then e2 else e3

:

if statements2
If statements

G |-- u1 ==> e1 : t1, q1

G |-- u2 ==> e2 : t2, q2

G |-- u3 ==> e3 : t3, q3

----------------------------------------------------------------

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
Function Application

G |-- u1 ==> e1 : t1, q1

G |-- u2 ==> e2 : t2, q2

----------------------------------------------------------------

G |-- u1 u2==> e1 e2

: a, q1 U q2 U {t1 = t2 -> a}

function application1
Function Application

G |-- u1 ==> e1 : t1, q1

G |-- u2 ==> e2 : t2, q2

----------------------------------------------------------------

G |-- u1 u2==> e1 e2

: a,

function declaration
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 declaration1
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
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
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
  • 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
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 machine1
Unification Machine
  • Base types & simple variables:

--------------------------------

(S,{int=int} U q) -> ???

unification machine2
Unification Machine
  • Base types & simple variables:

--------------------------------

(S,{int=int} U q) -> (S, q)

unification machine3
Unification Machine
  • Base types & simple variables:

--------------------------------

(S,{int=int} U q) -> (S, q)

------------------------------------

(S,{bool=bool} U q) -> ???

-----------------------------

(S,{a=a} U q) -> ???

unification machine4
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 machine5
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 machine6
Unification Machine
  • Functions:

----------------------------------------------

(S,{s11 -> s12= s21 -> s22} U q) ->

???

unification machine7
Unification Machine
  • Functions:

----------------------------------------------

(S,{s11 -> s12= s21 -> s22} U q) ->

(S, {s11 = s21, s12 = s22} U q)

occurs check
Occurs Check
  • What is the solution to {a = a -> a}?
occurs check1
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
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
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) -> ...
termination1
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
termination2
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,{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)

-----------------------------

(S,{a=a} U q) -> (S, q)

properties of solutions
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
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
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