HindleyMilner Type Inference CSE 340 Principles of Programming

  • Slides: 35
Download presentation
Hindley-Milner Type Inference CSE 340 – Principles of Programming Languages Fall 2016 Adam Doupé

Hindley-Milner Type Inference CSE 340 – Principles of Programming Languages Fall 2016 Adam Doupé Arizona State University http: //adamdoupe. com

Type Systems • In what we have seen so far, the programmer must declare

Type Systems • In what we have seen so far, the programmer must declare the types of the variables array [0. . 5] of int a; int i; a[i] = 1; Adam Doupé, Principles of Programming Languages 2

Type Systems • In what we have seen so far, the programmer must declare

Type Systems • In what we have seen so far, the programmer must declare the types of the variables array [0. . 5] of int a; string i; a[i] = 1; Adam Doupé, Principles of Programming Languages 3

Type Systems • In what we have seen so far, the programmer must declare

Type Systems • In what we have seen so far, the programmer must declare the types of the variables array [0. . 5] of int a; int i; a[i] = "testing"; Adam Doupé, Principles of Programming Languages 4

Parameterized Types • Some languages allow the programmer to declare parameterized types – Instead

Parameterized Types • Some languages allow the programmer to declare parameterized types – Instead of being specific to a given type, the specific type is given as a parameter • Generics in Java and C#, templates in C++ Adam Doupé, Principles of Programming Languages 5

import java. util. Random; public class Chooser{ static Random rand = new Random(); public

import java. util. Random; public class Chooser{ static Random rand = new Random(); public static <T> T choose(T first, T second) { return ((rand. next. Int() % 2) == 0)? first: second; } } class Parameterized. Types{ public static void main(String [] args) { int x = 100; int y = 999; System. out. println(Chooser. choose(x, y)); String a = "foo"; String b = "bar"; System. out. println(Chooser. choose(a, b)); } } Adam Doupé, Principles of Programming Languages 6

Explicit Polymorphism • Note that in the previous example, the programmer must declare the

Explicit Polymorphism • Note that in the previous example, the programmer must declare the parameterized types explicitly • Slightly different polymorphism than what is used in the object orientation context • The compiler/interpreter will allow a function to be called with different types (while still checking for type compatibility) Adam Doupé, Principles of Programming Languages 7

Implicit Polymorphism • The programmer does not need to specify the type parameters explicitly

Implicit Polymorphism • The programmer does not need to specify the type parameters explicitly – Dynamic languages have this property too • However, the type checker will, statically, attempt to assign the most general type to every construct in the program Adam Doupé, Principles of Programming Languages 8

Implicit Polymorphism fun foo(x) = x • What is the type of foo? –

Implicit Polymorphism fun foo(x) = x • What is the type of foo? – Function of T returns T – (T) -> T fun foo(x) = x; fun bar(y) = foo(y); • What is the type of bar and foo? – foo: Function of T returns T • (T) -> T – bar: Function of T returns T • (T) -> T Adam Doupé, Principles of Programming Languages 9

Implicit Polymorphism fun max(x, y) = if x < y then y else x

Implicit Polymorphism fun max(x, y) = if x < y then y else x • What is the type of max? – Function of (int, int) returns int – (int, int) -> int Adam Doupé, Principles of Programming Languages 10

Implicit Polymorphism fun max(cmp, x, y) = if cmp(x, y) then y else x

Implicit Polymorphism fun max(cmp, x, y) = if cmp(x, y) then y else x • What is the type of max? – Function of (T, T) returns bool, T, T) returns T – ((T, T) -> bool, T, T) -> T • max(<, 10, 200) • max(strcmp, "foo", "bar") Adam Doupé, Principles of Programming Languages 11

Implicit Polymorphism fun foo(a, b, c) = c(a[b]) • What is the type of

Implicit Polymorphism fun foo(a, b, c) = c(a[b]) • What is the type of foo? – Function of (Array of T, int, Function of (T) returns U – (Array of T, int, (T -> U)) -> U Adam Doupé, Principles of Programming Languages 12

Implicit Polymorphism fun foo(a, b, c) = a = 10; a(b[c]); • What is

Implicit Polymorphism fun foo(a, b, c) = a = 10; a(b[c]); • What is the type of foo? – Type error! Adam Doupé, Principles of Programming Languages 13

Hindley-Milner Type Checking • Hindley-Milner type checking is a general type inference approach –

Hindley-Milner Type Checking • Hindley-Milner type checking is a general type inference approach – It infers the types of constructs that are not explicitly declared – It leverages the constraints of the various constructs – It applies these constraints together with type unification to find the most general type for each construct (or can find a type error if there is one) • Full Hindley-Milner type checking is used in OCaml, F#, and Haskell Adam Doupé, Principles of Programming Languages 14

Type Constraints • To apply Hindley-Milner, we must first define the type constraints •

Type Constraints • To apply Hindley-Milner, we must first define the type constraints • Constant integers – …, -1, 0, 1, 2, . . . – Type = int • Constant real numbers –. . . , 0. 1, 2. 2, . . . other floating point numbers – Type = real • Constant booleans – true or false – Type = boolean • Constant strings – "foo", "bar", . . . – Type = string Adam Doupé, Principles of Programming Languages 15

Operators • Relational Operators a op b (T 1) op (T 2) a (T

Operators • Relational Operators a op b (T 1) op (T 2) a (T 3) b • op is <, <=, >, >=, !=, == • Constraints – T 1 = boolean – T 2 = T 3 Adam Doupé, Principles of Programming Languages 16

Operators • Arithmetic Operators a op b (T 1) op (T 2) a (T

Operators • Arithmetic Operators a op b (T 1) op (T 2) a (T 3) b • op is +, -, *, / • Constraints – T 1 = T 2 = T 3 Adam Doupé, Principles of Programming Languages 17

Operators • Array Access Operator a[b] (T 1) [] (T 2) a (T 3)

Operators • Array Access Operator a[b] (T 1) [] (T 2) a (T 3) b • Constraints – T 2 = array of T 1 – T 3 = int Adam Doupé, Principles of Programming Languages 18

Function Application • foo(x 1, x 2, …, xk) (R) apply (F) foo (T

Function Application • foo(x 1, x 2, …, xk) (R) apply (F) foo (T 1) x 1 (T 2) x 2 … (Tk) xk • Constraints – F = (T 1, T 2, …, Tk) -> R Adam Doupé, Principles of Programming Languages 19

Function Definition • fun foo(x 1, x 2, …, xk) = expr fun F

Function Definition • fun foo(x 1, x 2, …, xk) = expr fun F T 1, T 2, …, Tk foo (x 1, x 2, …, xk) (E) expr • Constraints – F = (T 1, T 2, …, Tk) -> E Adam Doupé, Principles of Programming Languages 20

If Expression • if (cond) then expr 1 else expr 2 (T 4) if

If Expression • if (cond) then expr 1 else expr 2 (T 4) if (T 1) cond (T 2) expr 1 (T 3) expr 2 • Constraints – T 1 = boolean – T 2 = T 3 = T 4 Adam Doupé, Principles of Programming Languages 21

Type Unification • Type unification is the process by which the constraints are propagated

Type Unification • Type unification is the process by which the constraints are propagated • Basic idea is simple – Start from the top of the tree – Every time you see a construct with unconstrained types, create a new type – If a construct is found to have type T 1 and also to have type T 2, then T 1 and T 2 must be the same type Adam Doupé, Principles of Programming Languages 22

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo a b c (1) (3) c (4) [] (5) a (6) b (2) (3) (4) (5) (6)Adam Doupé, Principles of Programming Languages 23

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo a T 1 b T 2 c T 3 (1) (3) c (4) [] (5) a (6) b (2) (3) (4) (5) (6)Adam Doupé, Principles of Programming Languages 24

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, T 3) -> T 4 a T 1 b T 2 c T 3 (1) (3) c (4) [] (5) a (6) b (2) (3) (4) (5) (6)Adam Doupé, Principles of Programming Languages 25

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, T 3) -> T 4 a T 1 b T 2 c T 3 (1) (2) (3) c (4) [] (5) a (6) b T 4 (3) (4) (5) (6)Adam Doupé, Principles of Programming Languages 26

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, T 3) -> T 4 a T 1 b T 2 c T 3 (1) (2) (3) c (4) [] (5) a (6) b T 4 (3) (4) T 5 (5) (6)Adam Doupé, Principles of Programming Languages 27

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, T 3) -> T 4 a T 1 b T 2 c T 3 (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (3) c (4) [] (5) a (6) b (5) (6)Adam Doupé, Principles of Programming Languages 28

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, T 3) -> T 4 a T 1 b T 2 c T 5 -> T 4 (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (3) c (4) [] (5) a (6) b (5) (6)Adam Doupé, Principles of Programming Languages 29

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, (T 5 ->T 4)) -> T 4 a T 1 b T 2 c T 5 -> T 4 (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (3) c (4) [] (5) a (6) b (5) (6)Adam Doupé, Principles of Programming Languages 30

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, (T 5 ->T 4)) -> T 4 a T 1 b T 2 c T 5 -> T 4 (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (5) Array of T 5 (6)Adam Doupé, Principles of Programming Languages (3) c (4) [] (5) a (6) b 31

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (T 1, T 2, (T 5 ->T 4)) -> T 4 a T 1 b T 2 c T 5 -> T 4 (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (5) Array of T 5 (6)Adam Doupé, int Principles of Programming Languages (3) c (4) [] (5) a (6) b 32

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (Array of T 5 , T 2, (T 5>T 4)) -> T 4 a Array of T 5 b T 2 c T 5 -> T 4 (3) c (4) [] (5) a (6) b (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (5)Adam Doupé, Array of Tof 5 Programming Languages Principles 33

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (Array of T 5, T 2, (T 5 ->T 4)) -> T 4 a Array of T 5 b int c T 5 -> T 4 (3) c (4) [] (5) a (6) b (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (5)Adam Array of T 5 of Programming Languages Doupé, Principles 34

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c)

fun foo(a, b, c) = c(a[b]) (1) def (2) apply foo (a, b, c) foo (Array of T 5, int, (T 5 ->T 4)) -> T 4 a Array of T 5 b int c T 5 -> T 4 (3) c (4) [] (5) a (6) b (1) (2) T 4 (3) T 5 -> T 4 (4) T 5 (5)Adam Array of T 5 of Programming Languages Doupé, Principles 35