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

principal type inference with subtyping
SMART_READER_LITE
LIVE PREVIEW

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 : . (


slide-1
SLIDE 1

Principal type inference with subtyping

Stephen Dolan and Alan Mycroft April 21, 2016

Computer Laboratory University of Cambridge

slide-2
SLIDE 2

select

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

2

slide-3
SLIDE 3

select

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

2

slide-4
SLIDE 4

select

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

2

slide-5
SLIDE 5

select

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

2

slide-6
SLIDE 6

Defining types

slide-7
SLIDE 7

Extensibility

When I add more types, no programs should break.

4

slide-8
SLIDE 8

Constructing types syntactically

Types: τ ::= bool | τ1 → τ2 | {ℓ1 : τ1, . . . , ℓn : τn}

5

slide-9
SLIDE 9

Constructing types syntactically

Types with subtyping: τ ::= bool | τ1 → τ2 | {ℓ1 : τ1, . . . , ℓn : τn} bool ≤ bool τ ′

1 ≤ τ1

τ2 ≤ τ ′

2

τ1 → τ2 ≤ τ ′

1 → τ ′ 2

{ℓ1 : τ1, . . . , ℓn : τn, . . . } ≤ {ℓ1 : τ1, . . . ℓn : τn} τ1 ≤ τ ′

1

. . . τn ≤ τ ′

n

{ℓ1 : τ1, . . . , ℓn : τn} ≤ {ℓ1 : τ ′

1, . . . , ℓn : τ ′ n}

5

slide-10
SLIDE 10

Constructing types syntactically

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

1 ≤ τ1

τ2 ≤ τ ′

2

τ1 → τ2 ≤ τ ′

1 → τ ′ 2

{ℓ1 : τ1, . . . , ℓn : τn, . . . } ≤ {ℓ1 : τ1, . . . ℓn : τn} τ1 ≤ τ ′

1

. . . τn ≤ τ ′

n

{ℓ1 : τ1, . . . , ℓn : τn} ≤ {ℓ1 : τ ′

1, . . . , ℓn : τ ′ n}

⊤ ≤ τ τ ≤ ⊤

5

slide-11
SLIDE 11

Constructing types syntactically

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

1 ≤ τ1

τ2 ≤ τ ′

2

τ1 → τ2 ≤ τ ′

1 → τ ′ 2

{ℓ1 : τ1, . . . , ℓn : τn, . . . } ≤ {ℓ1 : τ1, . . . ℓn : τn} τ1 ≤ τ ′

1

. . . τn ≤ τ ′

n

{ℓ1 : τ1, . . . , ℓn : τn} ≤ {ℓ1 : τ ′

1, . . . , ℓn : τ ′ n}

⊤ ≤ τ τ ≤ ⊤

5

slide-12
SLIDE 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

slide-13
SLIDE 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

slide-14
SLIDE 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

slide-15
SLIDE 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

slide-16
SLIDE 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

slide-17
SLIDE 17

Coproducts

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

7

slide-18
SLIDE 18

Coproducts

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

7

slide-19
SLIDE 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

slide-20
SLIDE 20

Type variables

How about type variables as metavariables?

8

slide-21
SLIDE 21

Type variables

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

8

slide-22
SLIDE 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

slide-23
SLIDE 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

slide-24
SLIDE 24

Inferring types

slide-25
SLIDE 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

slide-26
SLIDE 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

slide-27
SLIDE 27

When does ML unify?

Two inputs: introduce ⊓ Two outputs: introduce ⊔ Output used as an input: constraint τ + ≤ τ −

11

slide-28
SLIDE 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

slide-29
SLIDE 29

Atomic constraints

How do we get rid of α ≤ τ − or τ + ≤ α? Not substitution!

12

slide-30
SLIDE 30

Atomic constraints

How do we get rid of α ≤ τ − or τ + ≤ α? Not substitution!

∀ = Λ

12

slide-31
SLIDE 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

slide-32
SLIDE 32

Preserving the set of instances

It’s easy to remove constraints from set comprehensions:

13

slide-33
SLIDE 33

Preserving the set of instances

It’s easy to remove constraints from set comprehensions: {n2 + 17 | n ∈ N, n ≥ 5}

13

slide-34
SLIDE 34

Preserving the set of instances

It’s easy to remove constraints from set comprehensions: {n2 + 17 | n ∈ N, n ≥ 5} = {max(n, 5)2 + 17 | n ∈ N}

13

slide-35
SLIDE 35

Preserving the set of instances

It’s easy to remove constraints from set comprehensions: {n2 + 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

slide-36
SLIDE 36

Preserving the set of instances

It’s easy to remove constraints from set comprehensions: {n2 + 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

slide-37
SLIDE 37

Preserving the set of instances

It’s easy to remove constraints from set comprehensions: {n2 + 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

slide-38
SLIDE 38

Example

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

14

slide-39
SLIDE 39

Example

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

14

slide-40
SLIDE 40

Example

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

14

slide-41
SLIDE 41

Example

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

14

slide-42
SLIDE 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

slide-43
SLIDE 43

Example

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

14

slide-44
SLIDE 44

Example

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

14

slide-45
SLIDE 45

Example

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

14

slide-46
SLIDE 46

Example

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

14

slide-47
SLIDE 47

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

15