concepts of programming languages polymorphism and type...

31
Concepts of Programming Languages Polymorphism and Type Inference Lecturer: Gabriele Keller Tutor: Liam O’Connor University of New South Wales School of Computer Sciences & Engineering Sydney, Australia COMP 3161/9161 Week 8 Tuesday, 30 April 13

Upload: others

Post on 18-Apr-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Concepts of Programming LanguagesPolymorphism and Type Inference

Lecturer: Gabriele KellerTutor: Liam O’ConnorUniversity of New South WalesSchool of Computer Sciences & EngineeringSydney, Australia

COMP 3161/9161 Week 8

Tuesday, 30 April 13

Parametric Polymorphism

• Example: swap the elements of a pair (in Haskell)

• What is swap’s type?★In Haskell:

★ in MinHs:

swap (x, y) = (y, x)

swap :: (a, b) -> (b, a)

letfun swapIntBool :: (Int, Bool) -> (Bool, Int) pair = (snd pair, fst pair)

letfun swapBoolInt :: (Bool, Int) -> (Int, Bool) pair = (snd pair, fst pair).....

obviously, not the way to go!

Tuesday, 30 April 13

Parametric Polymorphism in MinHs

• Parametric polymorphism:

★ a and b are type variables

• Using a polymorphic function:

★when a polymorphic function is applied to a concrete value, the type variables are instantiated:

★ instantiates type variable

‣ a to Int

‣ b to Bool

letfun swap :: (a, b) -> (b, a) pair = (snd pair, fst pair)

swap (1, True)

Tuesday, 30 April 13

Parametric Polymorphism

• Assuming explicit typing ★ introduction of type variables needs to be explicit★ instantiation of type variables needs to be explicit

• Type abstraction

• Type instantiation

evaluates to a monomorphic function:

Type a in

Type b in letfun swap :: ((a, b) -> (b, a)) pair = (snd pair, fst pair)

inst (Type a in

inst (Type b in letfun swap :: ((a, b) -> (b, a)) pair = (snd pair, fst pair) Bool)

Int)

letfun swap :: (Int, Bool) -> (Bool, Int) pair = (snd pair, fst pair)

Tuesday, 30 April 13

Parametric Polymorphism

• What is the type of this function?

• Universal quantification:

★ it is ∀a.∀b.(a,b) ➔ (b,a)

★written in Haskell (leading forall optional)

Type a in

Type b in letfun swap :: ((a, b) -> (b, a)) pair = (snd pair, fst pair)

forall a b. (a, b) -> (b, a)

Tuesday, 30 April 13

Polymorphic MinHS - Concrete Syntax

Polytypes σ ::= τ | ∀ t. σMonotypes τ ::= Bool | Int | τ1 -> τ2

Expressions e ::= v

| inst (e, τ)| letfun id1 ::(τ1 -> τ2) id2 = e

| Type t in e | ...

only monotypes here!

Tuesday, 30 April 13

Polymorphic MinHS

• Valid Types:

‣ make sure we have no free type variables

t ∈ Δ

Δ ⊢ t ok

Δ ⊢ ∀ t. σ okP

Δ ∪ {t} ⊢ σ okP t ∈ Δ

Δ ⊢ Bool ok Δ ⊢ Int ok Δ ⊢ τ1 ➔ τ2 ok

Δ ⊢ τ1 ok Δ ⊢ τ2 ok

Δ ⊢ σ ok

Δ ⊢ σ okP

Tuesday, 30 April 13

Polymorphic MinHS

• Typing rules

Δ ∪ {t}, Γ ⊢e : σ t ∉ Δ

Δ, Γ ⊢ Type (t.e ): ∀ t. σ

Δ, Γ ⊢ e : ∀ t. σ Δ ⊢ τ ok

Δ, Γ ⊢ Inst e τ : σ [t:= τ]

Tuesday, 30 April 13

Polymorphic MinHS

• Dynamic Semantics

Inst e τ ↦M Inst e’ τ e ↦M e’

Inst(Type(t.e)) τ ↦M e [t:= τ]

Tuesday, 30 April 13

Polymorphic MinHs

• Polymorphic MinHs with

★explicit introduction of type variables:

‣ Type a in letfun id :: (a -> a) x = x

★ explicit instantiation of type variables:

‣ inst(Type a in letfun id : (a->a) x = x,Bool)

:: ∀ a.a ➔ a

:: Bool ➔ Bool

Tuesday, 30 April 13

Polymorphic MinHs• Polymorphic functions are not first class citizens in MinHs, because we only

allow polytypes at the top level

★we can’t have a polymorphic function as return value

★we can’t have a function that demands a polymorphic function as argument value

• This restriction is not actually necessary for explicitly typed MinHs, since type checking would still work without (but it would be a problem for type inference)

Tuesday, 30 April 13

Polymorphic MinHs

• For which of the following types can we write total, terminating MinHs functions? (excluding error)

★∀ a. ∀ b.(a * b) ➔ (b * a)

★∀ a. ∀ b.(a + b) ➔ (b + a)

★∀ a. ∀ b.(a * b) ➔ a

★∀ a. ∀ b.(a + b) ➔ a

★∀ a. ∀ b.(a ➔ b) ➔ (b ➔ a)

★∀ a. ∀ b. ∀ c. ((a ➔ c) * (b ➔ c)) ➔ (a+b ➔c)

• The type constructors +, * , and ➔ correspond to the logical operators ∨,∧ and ⇒ . Types to theorems, and terminating programs to (constructive) proofs, and the type checker to a proof checker

Tuesday, 30 April 13

Principal Type

• Explicitly typed polymorphic languages are awkward to use

• We want the compiler to infer the type of an expression for us.

• What is the type of this function?

• Possible types

(1) Int* Int ➔ Int

(2) Int* Bool ➔ Int

(3) Int* (Int ➔ (Int + Bool)) ➔ Int

(4) ∀ a. Int* a ➔ Int

• Types (1) - (3) are instances of type (4)

letfun f x = (fst x) + 1

Tuesday, 30 April 13

Principal Type

• We write τ’≤ τ if τ’ is less general than τ, that is τ’ is an instance of τ

★Int* Int ➔ Int ≤ ∀ a. Int* a ➔ Int

★∀ a. Int* a ➔ Int ≤ ∀ a. ∀ b. b* a ➔ b

★∀ a. Int* a ➔ Int ≤ ∀ a. ∀ a. a* a ➔ a

★∀ a. a* a ➔ a ≤ ∀ a. ∀ b. b* a ➔ b

• We are interested in the most general type τ of the expression e such that e: τ’ implies τ’ ≤ τ

• This is called the principal type of the expression

Tuesday, 30 April 13

Implicitly Typed MinHs

• MinHs with the following changes:

★no type annotations for functions and type constructors (sum & product type)

★roll, unroll, rec not part of the language

‣ not possible with implicit typing

★no explicit type abstraction and instantiation

‣ Type and inst not part of the language

★Types of the build-in functions are part of the environment:

‣ Γ = {+: Int ➔ Int ➔ Int, fst: ∀ a. ∀ b.(a * b) ➔ a , ....}

★no overloading yet, e.g., == still only compares integers,

Tuesday, 30 April 13

Typing Rules

• Application, if-expression, variable and product rules stay the same:

Γ ⊢ e1 : τ1 ➔τ2 Γ ⊢ e2 : τ1

Γ ⊢ Apply e1 e2: τ2

Γ ⊢ e1 : τ1 Γ ⊢ e2 : τ2

Γ ⊢ Pair e1 e2 : τ1 * τ2

Γ ⊢ x : τx : τ ∈ Γ

Γ ⊢ If t1 t2 t3: τ

Γ ⊢ t1:Bool Γ ⊢ t2 : τ Γ ⊢ t3 : τ

Tuesday, 30 April 13

Typing Rules

• Inr and Inl introduce free type variables:

Γ ⊢ e1 : τ1

Γ ⊢ Inl e1 : τ1 + τ2

Γ ⊢ e2 : τ2

Γ ⊢ Inr e2 : τ1 + τ2

• Functions:

Γ∪{f : τ1 ➔τ2 , x : τ1 } ⊢ e : τ2

Γ ⊢Letfun( f.x.e): τ1 ➔τ2

could be any type

Tuesday, 30 April 13

Typing Rules• ∀ -introduction and elimination

Γ ⊢ e: ∀ t. τ Γ ⊢ e: τ [t:=τ’]

Γ ⊢ e : ∀ t. τ Γ ⊢ e: τ t ∉ TypeVars(Γ)

Tuesday, 30 April 13

Typing Rules

• Do the typing rules describe a type inference algorithm?★are they syntax directed?‣ no - ∀-introduction can always be applied

★can we view Γ and the expression as input, the type as output?‣ no - ∀-elimination rule may instantiate an expression to the wrong type!‣ no - function rule may introduce wrong type for x and f in environment

Γ ⊢ Apply Fst (Pair 1 True): Γ ⊢ Fst:Γ ⊢ Fst: ∀ a. ∀ b.(a * b) ➔ a

Γ ⊢ Pair 1 True: (Int*Bool)⋮

Γ ⊢ Letfun(f.x. (Plus x 1)): Γ∪{f:Bool ➔ Int , x : Bool } ⊢ Plus x 1:

(Bool*Bool) ➔ Bool

Tuesday, 30 April 13

Type Inference Algorithm

• Idea

★delay the instantiation of type variables until necessary

★“merge” required and computed argument type

★replace ∀-quantified variables by free, fresh variables

Γ ⊢ Apply Fst (Pair 1 True): Γ ⊢ Fst: (x * y) ➔ xΓ ⊢ Fst: ∀ a. ∀ b.(a * b) ➔ a

Γ ⊢ Pair 1 True: (Bool * Int)⋮

(x * y) ➔ x (Bool * Int) ➔ z

?

=

type of function we have type of function we need

[z :=Int] [y :=Int,x := Bool]

Tuesday, 30 April 13

Type Inference Algorithm

• In some cases, it is necessary to substitute variables on both sides:

or to replace variables with other variables

(Bool * x) =(y * Int)

(x * x) = (x * y)

?

?

[y :=Int,x := Bool] [y :=Int,x := Bool]

[y:=x] [y:=x]

Tuesday, 30 April 13

Unification

• A substitution S, with S τ = S τ’ is called a unifier of τ and τ’

• For the algorithm, we need the most general unifier (mgu)

• We write τ1 ∼ τ2 if S is an mgu of τ1 and τ2

• Examples:

★are there mgu’s for the following pairs of types?

S

(a *(a * a)) = (b * c) ?

Int = Bool ?

(a *(a * a)) = ((a * a) * a) ?

Tuesday, 30 April 13

Type Inference Algorithm

• Now back to our type inference algorithm:

Γ ⊢ x : τ [a1:=β1, ..... an:=βn]x : ∀ a1. .... ∀ an. τ ∈ Γ βi fresh

TΓ ⊢ e1 : τ1 T1TΓ ⊢ e2 : τ2

UT1T Γ ⊢ Apply e1 e2: Uα

T1 τ1 ∼ τ2 ➔αU

α fresh

T (Γ∪{ x : α1 }∪{ f : α2 } ) ⊢ e:τ T α2 ∼ T α1 ➔ τ

UTΓ ⊢Letfun( f.x.e): U (T α1 ➔ τ)α fresh

• Note• the rules are syntax directed• the environment and expression are input & unifier and type are output

U

Tuesday, 30 April 13

Type Inference

• Application example:

Γ ⊢ Apply Fst (1, True): U [ ] [ ] Int

Γ ⊢ Fst:

Fst: ∀ a. ∀ b.(a * b) ➔ a ∈Γ

(x* y) ➔ x Γ ⊢(1, True): (Int, Bool)

⋮(x* y) ➔ x (Int, Bool) ➔α∼

U

[ ] [ ]

where U = {α:=Int, y:=Bool,x:=Int]

TΓ ⊢ e1 : τ1 T1Γ ⊢ e2 : τ2

UT1T Γ ⊢ Apply e1 e2: Uα

T1 τ1 ∼ τ2 ➔αU

α fresh

Tuesday, 30 April 13

• Simple function example:

Type Inference

T (Γ∪{ x : α1 }∪{ f : α2 } ) ⊢ e:τ α2 ∼ T α1 ➔ τ

UTΓ ⊢Letfun( f.x.e): T α1 ➔ τα1 ,α2 fresh

U

Γ ⊢Letfun( f.x.(x, x)):

[α2 := α1 ➔ (α1, α1)][](Γ∪{ x : α1 }∪{ f : α2 } ) ⊢(x, x): (α1, α1) α2 ∼ [] (α1 ➔ (α1, α1))

α1, α2 fresh[α2:= α1 ➔ (α1, α1)] α1 ➔ (α1, α1)

Tuesday, 30 April 13

Type Inference

• Simple recursive function

T (Γ∪{ x : α1 }∪{ f : α2 } ) ⊢ e:τ α2 ∼ T α1 ➔ τ

UTΓ ⊢Letfun( f.x.e): T α1 ➔ τα1 ,α2 fresh

U

Γ ⊢Letfun( f.x.(App f x)): α1 ➔ α3[α1 ➔ α3/α2]

[(α1 ➔ α3)/α2](Γ∪{ x : α1 }∪{ f : α2 } ) ⊢ App f x: α3 α2 ∼ [α1 ➔ α3/α2] (α1 ➔ α3)

⋮ [α1 ➔ α3/α2]

[α1 ➔ α3/α2]

Tuesday, 30 April 13

Re-introducing the ∀-quantor

• None of the rules so far re-introduced the ∀-quantor

• Is this necessary at all?

• only necessary if we have let-bindings so polymorphic functions can be ‘exported’

let f = letfun g x = (x,x) in (f True, f 1)

let f x = (x,x) in (f True, f 1)

Tuesday, 30 April 13

Re-introducing the ∀-quantor

• Generalise over all variables which occur free in τ, but not in Γ

‣ Gen (Γ, τ) = ∀(TV(τ) \ TV(Γ)). τ

★Example:

‣ Gen ({x : a , y: Int}, (a,b) ➔ b) = ∀b. (a,b) ➔ b

T1 Γ ⊢ e1:τ T1 T2 Γ ⊢(Let e1 x.e2): τ’

T2 (T1Γ∪ x:Gen (T1Γ, τ)) ⊢ e2:τ’

Tuesday, 30 April 13

Type Inference

• Rules for Plus, Mult, Inl, and Inr, can be derived from their type in and the application rule

• The inference rules describe Robin Milner’s type inference algorithm W

• Returns the same typing scheme as the non-syntax directed rules discussed previously (modulo ∀-quantification)

Tuesday, 30 April 13

Unification

• Simple unification algorithm

‣ input: two type terms t1 and t2, ∀-quantified variables replaced by fresh, unique variables

‣ output: the most general unifier of t1 and t2 (if it exists)

Tuesday, 30 April 13

Unification

• Cases t1 and t2

★are both type variables v1 and v2

‣ if v1 = v2, return empty substitution‣ otherwise return [v1/v2]

★are both primitive types‣ if they are the same, return the empty substitution‣ otherwise, there is no unifier

★both are product types with t1 = (t11*t12) and t2 = (t21*t22)‣ compute the mgu S of t11 and t21

‣ compute the mgu S’ of S t12 and S t22

‣ return S ∪ S’★both function types, sum types (see product types)★only one is is type variable v, the other an arbitrary term t‣ if v occurs in t, there is no unifier (occurs check)‣ otherwise, return {v:= t}

★otherwise, there is no unifier

Tuesday, 30 April 13