principal type inference with subtyping
play

Principal type inference with subtyping Stephen Dolan and Alan - PowerPoint PPT Presentation

Principal type inference with subtyping Stephen Dolan and Alan Mycroft April 21, 2016 Computer Laboratory University of Cambridge select select p v d = if ( p v ) then v else d 2 select select p v d = if ( p v ) then v else d ML : . (


  1. Principal type inference with subtyping Stephen Dolan and Alan Mycroft April 21, 2016 Computer Laboratory University of Cambridge

  2. select select p v d = if ( p v ) then v else d 2

  3. select select p v d = if ( p v ) then v else d ML : ∀ α. ( α → bool) → α → α → α 2

  4. select select p v d = if ( p v ) then v else d ML : ∀ α. ( α → bool) → α → α → α v d argument to p result 2

  5. select select p v d = if ( p v ) then v else d ML : ∀ α. ( α → bool) → α → α → α v d argument to p result MLsub : ∀ α. ( α → bool) → α → β → ( α ⊔ β ) 2

  6. Defining types

  7. Extensibility When I add more types, no programs should break. 4

  8. Constructing types syntactically Types: τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } 5

  9. Constructing types syntactically Types with subtyping: τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } τ ′ τ 2 ≤ τ ′ 1 ≤ τ 1 2 τ 1 → τ 2 ≤ τ ′ 1 → τ ′ bool ≤ bool 2 { ℓ 1 : τ 1 , . . . , ℓ n : τ n , . . . } ≤ { ℓ 1 : τ 1 , . . . ℓ n : τ n } τ 1 ≤ τ ′ τ n ≤ τ ′ . . . 1 n { ℓ 1 : τ 1 , . . . , ℓ n : τ n } ≤ { ℓ 1 : τ ′ 1 , . . . , ℓ n : τ ′ n } 5

  10. Constructing types syntactically Types with subtyping, least and greatest types: τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } | ⊥ | ⊤ τ ′ τ 2 ≤ τ ′ 1 ≤ τ 1 2 τ 1 → τ 2 ≤ τ ′ 1 → τ ′ bool ≤ bool 2 { ℓ 1 : τ 1 , . . . , ℓ n : τ n , . . . } ≤ { ℓ 1 : τ 1 , . . . ℓ n : τ n } τ 1 ≤ τ ′ τ n ≤ τ ′ . . . 1 n { ℓ 1 : τ 1 , . . . , ℓ n : τ n } ≤ { ℓ 1 : τ ′ 1 , . . . , ℓ n : τ ′ n } ⊤ ≤ τ τ ≤ ⊤ 5

  11. Constructing types syntactically Types with lattice subtyping: τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } | ⊥ | ⊤ τ ′ τ 2 ≤ τ ′ 1 ≤ τ 1 2 τ 1 → τ 2 ≤ τ ′ 1 → τ ′ bool ≤ bool 2 { ℓ 1 : τ 1 , . . . , ℓ n : τ n , . . . } ≤ { ℓ 1 : τ 1 , . . . ℓ n : τ n } τ 1 ≤ τ ′ τ n ≤ τ ′ . . . 1 n { ℓ 1 : τ 1 , . . . , ℓ n : τ n } ≤ { ℓ 1 : τ ′ 1 , . . . , ℓ n : τ ′ n } ⊤ ≤ τ τ ≤ ⊤ 5

  12. What’s going on here? F ( A ) = Bool( A ) + Func( A ) + Rec( A ) Bool( A ) = bool Func( A ) = A × A Rec( A ) = L ⇀ A Take the initial algebra of F : Set → Set 6

  13. What’s going on here? F ( A ) = Bool( A ) + Func( A ) + Rec( A ) Bool( A ) = bool Func( A ) = A − × A Rec( A ) = L ⇀ A Take the initial algebra of F : Pos → Pos . 6

  14. What’s going on here? F ( A ) = Bool( A ) + Func( A ) + Rec( A ) Bool( A ) = (bool) ⊤ ⊥ Func( A ) = ( A − × A ) ⊤ ⊥ Rec( A ) = ( L ⇀ A ) ⊤ ⊥ Take the initial algebra of F : Pos ⊤ ⊥ → Pos ⊤ ⊥ . 6

  15. What’s going on here? F ( A ) = Bool( A ) + Func( A ) + Rec( A ) Bool( A ) = (bool) ⊤ ⊥ Func( A ) = ( A − × A ) ⊤ ⊥ Rec( A ) = ( L ⇀ A ) ⊤ ⊥ Take a lattice of types, forget that it’s a lattice, apply F : Pos ⊤ ⊥ → Pos ⊤ ⊥ , and notice that the result happens to be a lattice. 6

  16. What’s going on here? F ( A ) = Bool( A ) + Func( A ) + Rec( A ) Bool( A ) = (bool) ⊤ ⊥ Func( A ) = ( A − × A ) ⊤ ⊥ Rec( A ) = ( L ⇀ A ) ⊤ ⊥ Take the initial algebra of F : Lat → Lat . 6

  17. Coproducts τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } The | should be the coproduct. Not always union! 7

  18. Coproducts τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } The | should be the coproduct. Not always union! We get some new types: ( τ → τ ) ⊓ { foo : τ } 7

  19. Coproducts τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } The | should be the coproduct. Not always union! We get some new types: ( τ → τ ) ⊓ { foo : τ } ≤ bool 7

  20. Type variables How about type variables as metavariables ? 8

  21. Type variables How about type variables as metavariables ? Pottier’s tricky example: τ = ⊥ | τ → τ | ⊤ ( ⊥ → ⊤ ) → ⊥ ≤ ( α → ⊥ ) ⊔ α This is true, by case analysis . . . 8

  22. Type variables How about type variables as metavariables ? Pottier’s tricky example: τ = ⊥ | τ → τ | ⊤ ( ⊥ → ⊤ ) → ⊥ ≤ ( α → ⊥ ) ⊔ α This is true, by case analysis . . . until we extend the type system α = ( ⊤ ◦ ◦ → ⊥ ) → ⊥ 8

  23. Type variables How about type variables as metavariables ? Pottier’s tricky example: τ = ⊥ | τ → τ | ⊤ ( ⊥ → ⊤ ) → ⊥ ≤ ( α → ⊥ ) ⊔ α This is true, by case analysis . . . until we extend the type system α = ( ⊤ ◦ ◦ → ⊥ ) → ⊥ We need type variables as a free algebra . Syntactically, add them as opaque indeterminates: τ ::= bool | τ 1 → τ 2 | { ℓ 1 : τ 1 , . . . , ℓ n : τ n } | α 8

  24. Inferring types

  25. Polarity We have lots of types, but they’re not all useful all the time. τ 1 ⊔ τ 2 describes an output that may be τ 1 or may be τ 2 . τ 1 ⊓ τ 2 describes an input that must be τ 1 and must be τ 2 10

  26. Polarity We have lots of types, but they’re not all useful all the time. τ 1 ⊔ τ 2 describes an output that may be τ 1 or may be τ 2 . τ 1 ⊓ τ 2 describes an input that must be τ 1 and must be τ 2 Use positive types τ + for outputs, and negative types τ − for inputs: τ + ::= α | τ + ⊔ τ + | ⊥ | unit | τ − → τ + τ − ::= α | τ − ⊓ τ − | ⊤ | unit | τ + → τ − 10

  27. When does ML unify? Two inputs : introduce ⊓ Two outputs : introduce ⊔ Output used as an input : constraint τ + ≤ τ − 11

  28. When does ML unify? Two inputs : introduce ⊓ Two outputs : introduce ⊔ Output used as an input : constraint τ + ≤ τ − Handling ⊔ and ⊓ is easy, thanks to polarity: τ 1 ⊔ τ 2 ≤ τ 3 iff τ 1 ≤ τ 3 , τ 2 ≤ τ 3 τ 1 ≤ τ 2 ⊓ τ 3 iff τ 1 ≤ τ 2 , τ 1 ≤ τ 3 11

  29. Atomic constraints How do we get rid of α ≤ τ − or τ + ≤ α ? Not substitution! 12

  30. Atomic constraints How do we get rid of α ≤ τ − or τ + ≤ α ? Not substitution! ∀ � = Λ 12

  31. Atomic constraints How do we get rid of α ≤ τ − or τ + ≤ α ? Not substitution! ∀ � = Λ ML’s ∀ is more like a set comprehension. These are the same: ∀ α ∀ β. α → β → α ∀ β ∀ α. α → β → α because these are the same { α → β → α | α, β types } { α → β → α | β, α types } 12

  32. Preserving the set of instances It’s easy to remove constraints from set comprehensions: 13

  33. Preserving the set of instances It’s easy to remove constraints from set comprehensions: { n 2 + 17 | n ∈ N , n ≥ 5 } 13

  34. Preserving the set of instances It’s easy to remove constraints from set comprehensions: { n 2 + 17 | n ∈ N , n ≥ 5 } = { max( n , 5) 2 + 17 | n ∈ N } 13

  35. Preserving the set of instances It’s easy to remove constraints from set comprehensions: { n 2 + 17 | n ∈ N , n ≥ 5 } = { max( n , 5) 2 + 17 | n ∈ N } Thinking of type schemes as set comprehensions, we can do the same: α → α | α ≤ { isgood : bool } 13

  36. Preserving the set of instances It’s easy to remove constraints from set comprehensions: { n 2 + 17 | n ∈ N , n ≥ 5 } = { max( n , 5) 2 + 17 | n ∈ N } Thinking of type schemes as set comprehensions, we can do the same: α → α | α ≤ { isgood : bool } = ( α ⊓ { isgood : bool } ) → ( α ⊓ { isgood : bool } ) 13

  37. Preserving the set of instances It’s easy to remove constraints from set comprehensions: { n 2 + 17 | n ∈ N , n ≥ 5 } = { max( n , 5) 2 + 17 | n ∈ N } Thinking of type schemes as set comprehensions, we can do the same: α → α | α ≤ { isgood : bool } = ( α ⊓ { isgood : bool } ) → ( α ⊓ { isgood : bool } ) = ( α ⊓ { isgood : bool } ) → α 13

  38. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] 14

  39. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] list[ { isgood : bool }⊓ α ] → list[ α ] ≤ list[ { isgood : bool , x : int } ] → β 14

  40. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] list[ α ] ≤ β list[ { isgood : bool , x : int } ] ≤ list[ { isgood : bool } ⊓ α ] 14

  41. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] list[ α ] ≤ β { isgood : bool , x : int } ≤ { isgood : bool } ⊓ α 14

  42. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] list[ α ] ≤ β { isgood : bool , x : int } ≤ { isgood : bool } { isgood : bool , x : int } ≤ α 14

  43. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] list[ α ] ≤ β { isgood : bool , x : int } ≤ α 14

  44. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] β + �→ β ⊔ list[ α ] α + �→ α ⊔ { isgood : bool , x : int } 14

  45. Example filter good : list[ { isgood : bool } ⊓ α ] → list[ α ] things : list[ { isgood : bool , x : int } ] β ⊔ list[ α ⊔ { isgood : bool , x : int } ] 14

Recommend


More recommend