polymorphism subtyping and type inference in mlsub
play

Polymorphism, Subtyping, and Type Inference in MLsub Stephen Dolan - PowerPoint PPT Presentation

Polymorphism, Subtyping, and Type Inference in MLsub Stephen Dolan and Alan Mycroft January 18, 2017 Computer Laboratory University of Cambridge The select function select p v d = if ( p v ) then v else d In ML, select has type scheme . (


  1. Polymorphism, Subtyping, and Type Inference in MLsub Stephen Dolan and Alan Mycroft January 18, 2017 Computer Laboratory University of Cambridge

  2. The select function select p v d = if ( p v ) then v else d In ML, select has type scheme ∀ α. ( α → bool ) → α → α → α 2

  3. Data flow in select select p v d = if ( p v ) then v else d v d argument to p result 3

  4. Data flow in select select p v d = if ( p v ) then v else d v d argument to p result In MLsub, select has this type scheme: ∀ α, β. ( α → bool ) → α → β → ( α ⊔ β ) 3

  5. The MLsub Type System

  6. Γ ⊢ e : τ

  7. Γ ⊢ e : τ

  8. Expressions of MLsub We have functions λ x . e x e 1 e 2 ... and records { ℓ 1 = e 1 , . . . , ℓ n = e n } e .ℓ ... and booleans true false if e 1 then e 2 else e 3 ... and let ˆ let ˆ x = e 1 in e 2 x 7

  9. Γ ⊢ e : τ

  10. Typing rules of MLsub MLsub is ML + Γ ⊢ e : τ 1 ( Sub ) τ 1 ≤ τ 2 Γ ⊢ e : τ 2 9

  11. Γ ⊢ e : τ

  12. Constructing Types The standard definition of types looks like: τ ::= ⊥ | τ → τ | ⊤ (ignoring records and booleans for now) 11

  13. Constructing Types The standard definition of types looks like: τ ::= ⊥ | τ → τ | ⊤ (ignoring records and booleans for now) with a subtyping relation like: τ ′ τ 2 ≤ τ ′ 1 ≤ τ 1 2 τ 1 → τ 2 ≤ τ ′ 1 → τ ′ ⊥ ≤ τ τ ≤ ⊤ 2 11

  14. Lattices These types form a lattice: • least upper bounds τ 1 ⊔ τ 2 • greatest lower bounds τ 1 ⊓ τ 2 12

  15. Lattices These types form a lattice: • least upper bounds τ 1 ⊔ τ 2 • greatest lower bounds τ 1 ⊓ τ 2 e 1 : τ 1 e 2 : τ 2 if rand () then e 1 else e 2 : τ 1 ⊔ τ 2 12

  16. Bizzarely difficult questions Is this true, for all α ? α → α ≤ ⊥ → ⊤ 13

  17. Bizzarely difficult questions Is this true, for all α ? α → α ≤ ⊥ → ⊤ How about this? ( ⊥ → ⊤ ) → ⊥ ≤ ( α → ⊥ ) ⊔ α 13

  18. Bizzarely difficult questions Is this true, for all α ? α → α ≤ ⊥ → ⊤ How about this? ( ⊥ → ⊤ ) → ⊥ ≤ ( α → ⊥ ) ⊔ α Yes, it turns out, by case analysis on α . 13

  19. Bizzarely difficult questions Is this true, for all α ? α → α ≤ ⊥ → ⊤ How about this? ( ⊥ → ⊤ ) → ⊥ ≤ ( α → ⊥ ) ⊔ α Yes, it turns out, by case analysis on α . And only by case analysis. 13

  20. Extensibility ◦ Let’s add a new type of function τ 1 → τ 2 . 14

  21. Extensibility ◦ Let’s add a new type of function τ 1 → τ 2 . It’s a supertype of τ 1 → τ 2 “function that may have side effects” 14

  22. Extensibility ◦ Let’s add a new type of function τ 1 → τ 2 . It’s a supertype of τ 1 → τ 2 “function that may have side effects” Now we have a counterexample: ◦ ◦ α = ( ⊤ → ⊥ ) → ⊥ 14

  23. Extensibility and vacuous reasoning τ r = some record type τ f = some function type Is τ r ⊓ τ f ≤ bool? 15

  24. Extensibility and vacuous reasoning τ r = some record type τ f = some function type Is τ r ⊓ τ f ≤ bool? Yes, vacuously. 15

  25. Extensible type systems Two techniques give us an extensible system: • Add explicit type variables as indeterminates gets rid of case analysis 16

  26. Extensible type systems Two techniques give us an extensible system: • Add explicit type variables as indeterminates gets rid of case analysis • Require a distributive lattice gets rid of vacuous reasoning 16

  27. Resulting types We end up with all the standard types 17

  28. Resulting types We end up with all the standard types ... with the same subtyping order 17

  29. Resulting types We end up with all the standard types ... with the same subtyping order ... but we identify fewer of the weird types { foo : bool } ⊓ ( ⊤ → ⊤ ) �≤ bool 17

  30. Type Inference with Polar Types

  31. Input and output types τ ⊔ τ ′ : produces a value which is a τ or a τ ′ τ ⊓ τ ′ : requires a value which is a τ and a τ ′ ⊔ is for outputs, and ⊓ is for inputs. 19

  32. Input and output types τ ⊔ τ ′ : produces a value which is a τ or a τ ′ τ ⊓ τ ′ : requires a value which is a τ and a τ ′ ⊔ is for outputs, and ⊓ is for inputs. Divide types into • output types τ + • input types τ − 19

  33. Polar types τ + ::= bool | τ − 1 → τ + 2 | { ℓ 1 : τ + 1 , . . . , ℓ n : τ + n } | α | τ + 1 ⊔ τ + 2 | ⊥ | µα.τ + τ − ::= bool | τ + 1 → τ − 2 | { ℓ 1 : τ − 1 , . . . , ℓ n : τ − n } | α | τ − 1 ⊓ τ − 2 | ⊤ | µα.τ − 20

  34. Cases of unification In HM inference, unification happens in three situations: • Unifying two input types • Unifying two output types • Using the output of one expression as input to another 21

  35. Cases of unification In HM inference, unification happens in three situations: • Unifying two input types Introduce ⊓ • Unifying two output types Introduce ⊔ • Using the output of one expression as input to another τ + ≤ τ − constraint 21

  36. Eliminating variables, ML-style Suppose we have an identity function α → α 22

  37. Eliminating variables, ML-style Suppose we have an identity function, which uses its argument as a τ α → α | α = τ 22

  38. Eliminating variables, ML-style Suppose we have an identity function, which uses its argument as a τ α → α | α = τ ≡ ∀ τ → τ 22

  39. Eliminating variables, ML-style Suppose we have an identity function, which uses its argument as a τ α → α | α = τ ≡ ∀ τ → τ The substitution [ τ/α ] solves the constraint α = τ 22

  40. Eliminating variables, MLsub-style Suppose we have an identity function, which uses its argument as a τ − . α → α | α ≤ τ − 23

  41. Eliminating variables, MLsub-style Suppose we have an identity function, which uses its argument as a τ − . α → α | α ≤ τ − ≡ ∀ ( α ⊓ τ − ) → α 23

  42. Eliminating variables, MLsub-style Suppose we have an identity function, which uses its argument as a τ − . α → α | α ≤ τ − ≡ ∀ ( α ⊓ τ − ) → α The bisubstitution [ α ⊓ τ − /α − ] solves α ≤ τ − 23

  43. Decomposing constraints We only need to decompose constraints of the form τ + ≤ τ − . τ 1 ⊔ τ 2 ≤ τ 3 ≡ τ 1 ≤ τ 3 , τ 2 ≤ τ 3 τ 1 ≤ τ 2 ⊓ τ 3 ≡ τ 1 ≤ τ 2 , τ 1 ≤ τ 3 Thanks to the input/output type distinction, the hard cases of τ 1 ⊓ τ 2 ≤ τ 3 and τ 1 ≤ τ 2 ⊔ τ 3 can never come up. 24

  44. Combining solutions We solve a system of multiple constraints C 1 , C 2 by: • Solving C 1 , giving a bisubstitution ξ • Applying that to C 2 • Solving ξ C 2 , giving a bisubstitution ζ Then ξ ◦ ζ solves the system C 1 , C 2 . 25

  45. Summary MLsub infers types by walking the syntax of the program, but must deal with subtyping constraints rather than just equalities. Thanks to: • algebraically well-behaved types • polar types, restricting occurrences of ⊔ and ⊓ • the biunification algorithm we can always handle these constraints, producing a principal type. 26

  46. Future work { -# LANGUAGE ?? #- } • RankNTypes? • GADTs? • TypeFamilies? • ... 27

  47. Questions? http://www.cl.cam.ac.uk/~sd601/mlsub stephen.dolan@cl.cam.ac.uk 28

  48. Mutable references References are generally considered “invariant”. Instead, consider ref a two-argument constructor ( α, β ) ref with operations: make : ( α, α ) ref get : ( ⊥ , β ) ref → β set : ( α, ⊤ ) ref → α → unit 29

Recommend


More recommend