Polymorphism and System-F (OV) Theorie der Programmierung SoSe 2014 FAU
the occurrence of something in several different forms Polymorphism?
Polymorphic systems Type systems that allow a single piece of code to be used with multiple types [... ] (Pierce, Types and Programming Languages (2002))
Polymorphic systems Examples Operator overloading in C++ int operator+(int, int); string operator+(const string&, const string&);... int n = 5 + 3; string s = "hello" + " " + "world";
Polymorphic systems Examples Method overriding C++ class C {... public: int dosomething(); } class D: public C {... public: int dosomething(); } int a = C().doSomething() + D().doSomething();
Polymorphic systems Examples Dynamic dispatch in Java interface Figure { public void draw(); } class Circle implements Figure {... } class Triangle implements Figure {... }... public void drawall(figure [] figs) { for (int i = 0; i < figs.length; i++) { figs[i].draw(); } }
Polymorphic systems Examples Generics in Java class Stack<T> { public Stack() {... } public T top() {... } public void pop() {... } public void push(t e) {... } }... public void dosomething() { Stack<Integer> si =... Stack<String> ss =... si.push(42); ss.push("hello"); }
Polymorphic systems Examples Polymorphic datatypes and functions in Haskell data List a = Nil Cons a (List a) append :: List a -> List a -> List a append Nil ys = ys append (Cons x xs) ys = Cons x (append xs ys)
A classification of polymorphism Parametric polymorphism. Ad-hoc polymorphism. A single portion of code is given a generic type. The behaviour is uniform on all instances. Each instance may exhibit a different behaviour. - Terminology is from Strachey, Fundamental Concepts in Programming Languages (1967) - We follow Pierce, Types and Programming Languages (2002)
Polymorphic systems Revisited Operator overloading in C++ int operator+(int, int); string operator+(const string&, const string&);... int n = 5 + 3; string s = "hello" + " " + "world";
Polymorphic systems Revisited Operator overloading in C++ Ad-hoc! int operator+(int, int); string operator+(const string&, const string&);... int n = 5 + 3; string s = "hello" + " " + "world";
Polymorphic systems Revisited Method overriding C++ class C {... public: int dosomething(); } class D: public C {... public: int dosomething(); } int a = C().doSomething() + D().doSomething();
Polymorphic systems Revisited Method overriding C++ Ad-hoc! class C {... public: int dosomething(); } class D: public C {... public: int dosomething(); } int a = C().doSomething() + D().doSomething();
Polymorphic systems Revisited Dynamic dispatch in Java interface Figure { public void draw(); } class Circle implements Figure {... } class Triangle implements Figure {... }... public void drawall(figure [] figs) { for (int i = 0; i < figs.length; i++) { figs[i].draw(); } }
Polymorphic systems Revisited Dynamic dispatch in Java Ad-hoc! interface Figure { public void draw(); } class Circle implements Figure {... } class Triangle implements Figure {... }... public void drawall(figure [] figs) { for (int i = 0; i < figs.length; i++) { figs[i].draw(); } }
Polymorphic systems Revisited Polymorphic datatypes and functions in Haskell data List a = Nil Cons a (List a) append :: List a -> List a -> List a append Nil ys = ys append (Cons x xs) ys = Cons x (append xs ys)
Polymorphic systems Revisited Polymorphic datatypes and functions in Haskell Parametric! data List a = Nil Cons a (List a) append :: List a -> List a -> List a append Nil ys = ys append (Cons x xs) ys = Cons x (append xs ys)
Polymorphic systems Revisited Generics in Java class Stack<T> { public Stack() {... } public T top() {... } public void pop() {... } public void push(t e) {... }... public void dosomething() { Stack<Integer> si =... Stack<String> ss =... si.push(42); ss.push("hello"); } }
Polymorphic systems Revisited Generics in Java Parametric...? class Stack<T> { public Stack() {... } public T top() {... } public void pop() {... } public void push(t e) {... }... public void dosomething() { Stack<Integer> si =... Stack<String> ss =... si.push(42); ss.push("hello"); } }
Polymorphic systems Revisited Generics in Java... are not necessarily uniform!! class Stack<T> { public Stack() {... } public T top() {... } public void pop() {... } public void push(t e) { if ( e instanceof String ) { dosomethingweird((string) e); } else { donormalpush(e); } } }
Parametric polymorphism (true) polymorphism Ad-hoc polymorphism in all its flavours is a nice convenience (but in the end just a bunch of functions that share the same name) Parametric polymorphism is more fundamental and powerful (in a way to be made precise later) Up next: a polymorphic type system for the λ-calculus
Parametric polymorphism (true) polymorphism Ad-hoc polymorphism in all its flavours is a nice convenience (but in the end just a bunch of functions that share the same name) Parametric polymorphism is more fundamental and powerful (in a way to be made precise later) Up next: a polymorphic type system for the λ-calculus! Why is the STLC not enough?
Recap: the STLC Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β
Recap: the STLC Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β Polymorphism in practice, a silly example id :: a -> a id = \x -> x (Haskell code) silly :: Int silly = (\x y -> x) (id True) (id 42) Can we type silly in the STLC?
System F Discovered almost simultaneously by: Girard (1972), while working on proof-theory Reynolds (1974), while working on polymorphism (he called it polymorphic λ-calculus )
System F Discovered almost simultaneously by: Girard (1972), while working on proof-theory Reynolds (1974), while working on polymorphism (he called it polymorphic λ-calculus )! Two versions of System-F: à la Curry and à la Church! We shall see both
From STLC to System F (à la Curry) Types: α, β ::= a α β (a TypeVars) Terms: s, t ::= x st λx.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β
From STLC to System F (à la Curry) Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β
From STLC to System F (à la Curry) Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ s : a.α
From STLC to System F (à la Curry) Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ s : a.α ( e) Γ s : a.α Γ s : (α[a := β])
From STLC to System F (à la Curry) Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ s : a.α ( e) Γ s : a.α Γ s : (α[a := β]) We can indeed type silly in System F!
Some basic properties of System F Theorem (Preservation straightforward proof) If Γ s : α and s β t, then Γ t : α. Theorem (Normalization Girard (1972)) If Γ s : α, then s is strongly normalizing.
Some basic properties of System F In fact: any computable function proved total using SO Arithmetic can be written in System F! All primitive recursive functions Even the Ackermann function Intuition: a compiler an interpreter
Church encoding in System F Natural numbers N := a.(a a) a a zero : N zero = λf a. a succ : N N succ = λn f a. f (n f a)
Church encoding in System F Natural numbers N := a.(a a) a a zero : N zero = λf a. a succ : N N succ = λn f a. f (n f a) add : N N N add = λn m. n succ m
Church encoding in System F Natural numbers N := a.(a a) a a zero : N zero = λf a. a succ : N N succ = λn f a. f (n f a) add : N N N add = λn m. n succ m mul : N N N mul = λn m. n (add m) zero
Church encodings in System F Natural numbers derivation of succ : N N N := a.(a a) a a Γ := n : N, f : a a, x : a Γ f : a a Γ n f x : a ( e) Γ f (n f x) : a ( i ) 2 n : N λf x. f (n f x) : (a a) a a ( i ) ( i ). n : N λf x. f (n f x) : N λn f x. f (n f x) : N N
Church encodings in System F Natural numbers derivation of succ : N N N := a.(a a) a a Γ := n : N, f : a a, x : a ( e) ( e) Γ n : a.(a a) a a Γ n : (a a) a a Γ f : a a Γ n f : a a ( e) Γ n f x : a. Γ f : a a Γ n f x : a ( e) Γ f (n f x) : a ( i ) 2 n : N λf x. f (n f x) : (a a) a a ( i ) ( i ) n : N λf x. f (n f x) : N λn f x. f (n f x) : N N Γ x : a
Church encoding in System F Products (a b) := r.(a b r) r pair : a b. a b (a b) pair =... fst : a b. (a b) a fst =... snd : a b. (a b) b snd =...
Church encoding in System F Products (a b) := r.(a b r) r pair : a b. a b (a b) pair = λ x y f. f x y fst : a b. (a b) a fst = λ p. p (λx y. x) snd : a b. (a b) b snd = λ p. p (λx y. y)
Church encoding in System F Products (a b) := r.(a b r) r pair : a b. a b (a b) pair = λ x y f. f x y fst : a b. (a b) a fst = λ p. p (λx y. x) snd : a b. (a b) b snd = λ p. p (λx y. y) How many non-equivalent implementations admits (a b) a?
Church encoding in System F Sums/co-products (a + b) := r.(a r) (b r) r injl : a b. a (a + b) injl =... injr : a b. b (a + b) injr =... case : a b s.(a s) (b s) (a + b) s case =...
Church encoding in System F Sums/co-products (a + b) := r.(a r) (b r) r injl : a b. a (a + b) injl = λ x f g. f x injr : a b. b (a + b) injr = λ y f g. g y case : a b s.(a s) (b s) (a + b) s case =...
Church encoding in System F Sums/co-products (a + b) := r.(a r) (b r) r injl : a b. a (a + b) injl = λ x f g. f x injr : a b. b (a + b) injr = λ y f g. g y case : a b s.(a s) (b s) (a + b) s case = λ f g p. p f g
Church encoding in System F Sums/co-products (a + b) := r.(a r) (b r) r injl : a b. a (a + b) injl = λ x f g. f x injr : a b. b (a + b) injr = λ y f g. g y case : a b s.(a s) (b s) (a + b) s case = λ f g p. p f g Can these types be implemented in an essentially different way?
Church encoding in System F Lists List a := r.r (a r r) r nil : a. List a nil =... cons : a. a List a List a cons =... length : a. List a N length =...
Church encoding in System F Lists List a := r.r (a r r) r nil : a. List a nil = λ u f. u cons : a. a List a List a cons = λ x l u f. f x (l u f ) length : a. List a N length =...
Church encoding in System F Lists List a := r.r (a r r) r nil : a. List a nil = λ u f. u cons : a. a List a List a cons = λ x l u f. f x (l u f ) length : a. List a N length = λ l. l zero (λx r. succ r)
Parametricity or why uniformity matters Intuition If we write a function with type a.α(a) we can t do anything on a-values fewer things can go wrong! - Introduced by Reynolds,Types, abstraction and parametric polymorphism (1983) as abstraction - Wadler s Theorems for free! (1989) uses it to derive free-theorems from polymorphic types
Parametricity or why uniformity matters Example singleton :: a -> List a singleton =... singletonint :: Int -> List Int singletonint =... If we want to be 100% sure of their correctness... how many unit tests do we need in each case? - Introduced by Reynolds,Types, abstraction and parametric polymorphism (1983) as abstraction - Wadler s Theorems for free! (1989) uses it to derive free-theorems from polymorphic types
All is very nice and good but...
All is very nice and good but... Theorem Type checking in System F à la Curry is undecidable. - Wells, Typability and type checking in the second-order lambda-calculus are equivalent and undecidable. (1994)
Where do we go from here? Use a weaker system Hindley-Milner type system Rank-2 polymorphism Add type annotations to λ-terms System F à la Church
Hindler-Milner types a weaker but practical system Roughly speaking... Types are restricted to prenex form : a b c.((a b) c) a.(( b.(a b)) a) Type instantiation restricted to quantifier-free types. ( -elimination needs to be modified)
System F, from Curry to Church Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ s : a.α ( e) Γ s : a.α Γ s : (α[a := β]) Reduction rules: (λx.s)t β s[x := t]
System F, from Curry to Church Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx:α.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ s : a.α ( e) Γ s : a.α Γ s : (α[a := β]) Reduction rules: (λx.s)t β s[x := t]
System F, from Curry to Church Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx:α.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx:α.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ s : a.α ( e) Γ s : a.α Γ s : (α[a := β]) Reduction rules: (λx.s)t β s[x := t]
System F, from Curry to Church Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx:α.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx:α.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ s : a.α ( e) Γ s : a.α Γ s : (α[a := β]) Reduction rules: (λ x:α.s)t β s[x := t]
System F, from Curry to Church Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx:α.s Λa.s (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx:α.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ Λa.s : a.α ( e) Γ s : a.α Γ s : (α[a := β]) Reduction rules: (λ x:α.s)t β s[x := t]
System F, from Curry to Church Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx:α.s Λa.s s@α (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx:α.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ Λa.s : a.α ( e) Γ s : a.α Γ s@β : (α[a := β]) Reduction rules: (λ x:α.s)t β s[x := t]
System F, from Curry to Church Types: α, β ::= a α β a.α (a TypeVars) Terms: s, t ::= x st λx:α.s Λa.s s@α (x TermVars) Typing rules: (axiom) Γ, x : α x : α ( i ) Γ, x : α s : β Γ λx:α.s : α β ( e) Γ s : α β Γ t : α Γ st : β ( i ) Γ s : α a / FV (Γ ) Γ Λa.s : a.α ( e) Γ s : a.α Γ s@β : (α[a := β]) Reduction rules: (λ x:α.s)t β s[x := t] (Λa.s)@α β s[a := α]
System F á la Church Examples id : a.a a id = Λa. λx:a. x f : Nat Nat f = λx:nat. succ (id@nat x)