F-ing Applicative Functors Andreas Rossberg, Google Claudio Russo, - - PowerPoint PPT Presentation

f ing applicative functors
SMART_READER_LITE
LIVE PREVIEW

F-ing Applicative Functors Andreas Rossberg, Google Claudio Russo, - - PowerPoint PPT Presentation

F-ing Applicative Functors Andreas Rossberg, Google Claudio Russo, MSR Derek Dreyer, MPI-SWS ML Workshop, Copenhagen 2012/09/13 The Functor Schism The Functor Schism SML: generative functors return fresh abstract types with


slide-1
SLIDE 1

F-ing Applicative Functors

Andreas Rossberg, Google Claudio Russo, MSR Derek Dreyer, MPI-SWS

ML Workshop, Copenhagen 2012/09/13

slide-2
SLIDE 2

The Functor Schism

slide-3
SLIDE 3

The Functor Schism

SML: “generative” functors ⇒ return “fresh” abstract types with each application

slide-4
SLIDE 4

The Functor Schism

SML: “generative” functors ⇒ return “fresh” abstract types with each application OCaml: “applicative” functors ⇒ return same abstract types with each application (to the “same” argument)

slide-5
SLIDE 5

The Functor Schism

SML: “generative” functors ⇒ return “fresh” abstract types with each application OCaml: “applicative” functors ⇒ return same abstract types with each application (to the “same” argument)

slide-6
SLIDE 6

Example: Set

slide-7
SLIDE 7

Example: Set

signature SET = { type elem type set val empty : set val add : elem → set → set val member : elem → set → bool }

slide-8
SLIDE 8

Example: Set

signature SET = { type elem type set val empty : set val add : elem → set → set val member : elem → set → bool } signature ORD = { type t val leq : t → t → bool }

slide-9
SLIDE 9

Example: Set

signature SET = { type elem type set val empty : set val add : elem → set → set val member : elem → set → bool } module Set (Elem : ORD) :> (SET where type elem = Elem.t) = { ... } signature ORD = { type t val leq : t → t → bool }

slide-10
SLIDE 10

Example: Set, generative

module A = Set Int A.member 3 (A.add 2 A.empty)

slide-11
SLIDE 11

Example: Set, generative

module A = Set Int module B = Set Int A.member 3 (B.add 2 B.empty)

slide-12
SLIDE 12

Example: Set, generative

module A = Set Int module B = Set Int A.member 3 (B.add 2 B.empty) (* ill-typed, A.set ≠ B.set *)

slide-13
SLIDE 13

Example: Set, applicative

module A = Set Int module B = Set Int A.member 3 (B.add 2 B.empty) (* well-typed, A.set = Set(Int).set = B.set *)

slide-14
SLIDE 14

The story, so far

Leroy [POPL 1995] – OCaml Russo [Thesis 1998 / ENTCS 2003] – Moscow ML Shao [ICFP 1999] Dreyer & Crary & Harper [POPL 2003]

slide-15
SLIDE 15

Plan

Issues Proposal Formalisation

slide-16
SLIDE 16

Why applicative functors?

slide-17
SLIDE 17

Why applicative functors?

Literature: motivated by higher-order functors

slide-18
SLIDE 18

Why applicative functors?

Literature: motivated by higher-order functors Practice: compilation units importing functors are higher-order functors in disguise

slide-19
SLIDE 19

Example: Map

signature MAP = { type key type map α val empty : map α val add : key → α → map α → map α val lookup : key → map α → option α } module Map : (Key : ORD) → MAP with type key = Key.t

slide-20
SLIDE 20

Example: Map

signature MAP = { type key type map α val empty : map α val add : key → α → map α → map α val lookup : key → map α → option α val domain : map α → ? } module Map : (Key : ORD) → MAP with type key = Key.t

slide-21
SLIDE 21

With generative Set, variant 1

signature MAP = { type key type map α module Set : SET with type elem = key val empty : map α val add : key → α → map α → map α val lookup : key → map α → option α val domain : map α → Set.set } module Map : (Key : ORD) → MAP with type key = Key.t

slide-22
SLIDE 22

With generative Set, variant 2

signature MAP = { type key type map α type set val empty : map α val add : key → α → map α → map α val lookup : key → map α → option α val domain : map α → set } module Map : (Key : ORD) → (Set : SET with type elem = Key.t) → MAP with type key = Key.t with type set = Set.t

slide-23
SLIDE 23

With applicative Set

signature MAP = { module Key : ORD type map α val empty : map α val add : Key.t → α → map α → map α val lookup : Key.t → map α → option α val domain : map α → Set(Key).set } module Map : (Key : ORD) → MAP with type key = Key.t

slide-24
SLIDE 24

Why applicative functors?

Two independent units can use the same generic data type without any need for cooperation A third unit using both is still able to exchange sets between them seamlessly (a.k.a. diamond import)

slide-25
SLIDE 25

Observation 0 Applicative functors are useful for modularity.

slide-26
SLIDE 26

Example: First-class modules

signature S = { type t; val v : t; val f : t → t } val p1 = pack { type t = int; val v = 6; val f = negate } : S val p2 = pack { type t = string; val v = “uh”; val f = id } : S

slide-27
SLIDE 27

Example: First-class modules

signature S = { type t; val v : t; val f : t → t } val p1 = pack { type t = int; val v = 6; val f = negate } : S val p2 = pack { type t = string; val v = “uh”; val f = id } : S val p = ref p1 module F {} = unpack !p : S

slide-28
SLIDE 28

Example: First-class modules

signature S = { type t; val v : t; val f : t → t } val p1 = pack { type t = int; val v = 6; val f = negate } : S val p2 = pack { type t = string; val v = “uh”; val f = id } : S val p = ref p1 module F {} = unpack !p : S module M1 = F {} p := p2 module M2 = F {}

slide-29
SLIDE 29

Example: First-class modules

signature S = { type t; val v : t; val f : t → t } val p1 = pack { type t = int; val v = 6; val f = negate } : S val p2 = pack { type t = string; val v = “uh”; val f = id } : S val p = ref p1 module F {} = unpack !p : S module M1 = F {} p := p2 module M2 = F {} M1.f M2.v (* oops, ka-boom! *)

slide-30
SLIDE 30

Observation 1 Applicativity can break type safety (with 1st-class modules).

slide-31
SLIDE 31

Example: Abstract names

signature NAME = { type name val new : () → name val eq : name → name → bool } module Name {} :> NAME = { type name = int val count = ref 0 val new () = ++count ; !count val eq = Int.eq }

slide-32
SLIDE 32

Example: Abstract names

module A = Name {} module B = Name {} val a = A.new () val b = B.new ()

slide-33
SLIDE 33

Example: Abstract names

module A = Name {} module B = Name {} val a = A.new () val b = B.new () a = b

slide-34
SLIDE 34

Example: Abstract names

module A = Name {} module B = Name {} val a = A.new () val b = B.new () a = b (* oops, true! *)

slide-35
SLIDE 35

Observation 2 Applicativity can break abstraction safety (of impure functors).

slide-36
SLIDE 36

Example: Set ordering

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.geq}

slide-37
SLIDE 37

Example: Set ordering

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.geq} val s1 = A.add 2 A.empty val s2 = B.add 3 s1

slide-38
SLIDE 38

Example: Set ordering

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.geq} val s1 = A.add 2 A.empty val s2 = B.add 3 s1 A.member 2 s2

slide-39
SLIDE 39

Example: Set ordering

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.geq} val s1 = A.add 2 A.empty val s2 = B.add 3 s1 A.member 2 s2 (* oops, false! *)

slide-40
SLIDE 40

Observation 3 Applicativity can break abstraction safety (of pure functors).

slide-41
SLIDE 41

Example: Set ordering, in Ocaml

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.geq}

slide-42
SLIDE 42

Example: Set ordering, in Ocaml

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.geq} val s1 = A.add 2 A.empty val s2 = B.add 3 s1

slide-43
SLIDE 43

Example: Set ordering, in Ocaml

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.geq} val s1 = A.add 2 A.empty val s2 = B.add 3 s1 (* type error, A.set ≠ B.set, because Set({...}).set not a path *)

slide-44
SLIDE 44

Set ordering in Ocaml, take 2

slide-45
SLIDE 45

Set ordering in Ocaml, take 2

module F (X : {}) = { type t = int val leq = if isFullMoon () then Int.leq else Int.geq }

slide-46
SLIDE 46

Set ordering in Ocaml, take 2

module F (X : {}) = { type t = int val leq = if isFullMoon () then Int.leq else Int.geq } (* returns one of the previous modules! *)

slide-47
SLIDE 47

Set ordering in Ocaml, take 2

module F (X : {}) = { type t = int val leq = if isFullMoon () then Int.leq else Int.geq } module Unit = {} module A = Set (F Unit) module B = Set (F Unit) (* returns one of the previous modules! *)

slide-48
SLIDE 48

Set ordering in Ocaml, take 2

module F (X : {}) = { type t = int val leq = if isFullMoon () then Int.leq else Int.geq } module Unit = {} module A = Set (F Unit) module B = Set (F Unit) val s1 = A.add 2 A.empty val s2 = B.add 3 s1 A.member 2 s2 (* returns one of the previous modules! *)

slide-49
SLIDE 49

Set ordering in Ocaml, take 2

module F (X : {}) = { type t = int val leq = if isFullMoon () then Int.leq else Int.geq } module Unit = {} module A = Set (F Unit) module B = Set (F Unit) val s1 = A.add 2 A.empty val s2 = B.add 3 s1 A.member 2 s2 (* oops, false! A.set = Set(F Unit).set = B.set *) (* returns one of the previous modules! *)

slide-50
SLIDE 50

Observation 4 Impure applications in paths breaks abstraction safety (even of pure functors).

slide-51
SLIDE 51

Type Equivalence in Ocaml

module A = Set {type t = int; val leq = Int.leq} module B = Set {type t = int; val leq = Int.leq} val s1 = A.add 2 A.empty val s2 = B.add 3 s1 A.member 2 s2 (* type error, A.set ≠ B.set, because Set({...}).set not a path *)

slide-52
SLIDE 52

Type Equivalence in Ocaml (2)

module IntOrd = {type t = int; val leq = Int.leq} module IntOrd’ = IntOrd module A = Set IntOrd module B = Set IntOrd’ val s1 = A.add 2 A.empty val s2 = B.add 3 s1 A.member 2 s2 (* type error, A.set = Set(IntOrd).set ≠ Set(IntOrd’).set = B.set *)

slide-53
SLIDE 53

Observation 5 Syntactic path equivalence is

  • verly restrictive.
slide-54
SLIDE 54

Hm...

slide-55
SLIDE 55

Overcoming the Schism

slide-56
SLIDE 56

Overcoming the Schism

Support both applicative and generative functors

slide-57
SLIDE 57

Overcoming the Schism

Support both applicative and generative functors A functor is applicative if and only if it is pure

slide-58
SLIDE 58

Overcoming the Schism

Support both applicative and generative functors A functor is applicative if and only if it is pure ⇒ type system tracks purity

slide-59
SLIDE 59

Overcoming the Schism

Support both applicative and generative functors A functor is applicative if and only if it is pure ⇒ type system tracks purity Two modules are equivalent if and only if they define equivalent types and values

slide-60
SLIDE 60

Overcoming the Schism

Support both applicative and generative functors A functor is applicative if and only if it is pure ⇒ type system tracks purity Two modules are equivalent if and only if they define equivalent types and values ⇒ type system tracks value identity (while avoiding dependent types)

slide-61
SLIDE 61

Purity

slide-62
SLIDE 62

Purity

Only one form of functor expression, deemed pure iff: it does not unpack a first-class module it does not apply an impure functor all value bindings are “non-expansive” (value restriction)

slide-63
SLIDE 63

Purity

Only one form of functor expression, deemed pure iff: it does not unpack a first-class module it does not apply an impure functor all value bindings are “non-expansive” (value restriction) Two forms of functor type impure: (X : S1) → S2 pure: (X : S1) ⇒ S2

slide-64
SLIDE 64

Abstract Values

slide-65
SLIDE 65

Abstract Values

Every value binding is identified by an abstract value

slide-66
SLIDE 66

Abstract Values

Every value binding is identified by an abstract value Mere renamings retain identity (e.g., val x = A.y)

slide-67
SLIDE 67

Abstract Values

Every value binding is identified by an abstract value Mere renamings retain identity (e.g., val x = A.y) Other bindings define fresh abstract value

slide-68
SLIDE 68

Abstract Values

Every value binding is identified by an abstract value Mere renamings retain identity (e.g., val x = A.y) Other bindings define fresh abstract value Specifications (in signatures) declare abstract values

slide-69
SLIDE 69

Abstract Values

Every value binding is identified by an abstract value Mere renamings retain identity (e.g., val x = A.y) Other bindings define fresh abstract value Specifications (in signatures) declare abstract values Formally, abstract values are phantom type variables, quantified and matched in same manner as abstract types

slide-70
SLIDE 70

Abstract Values

Every value binding is identified by an abstract value Mere renamings retain identity (e.g., val x = A.y) Other bindings define fresh abstract value Specifications (in signatures) declare abstract values Formally, abstract values are phantom type variables, quantified and matched in same manner as abstract types Refinement of SML90’s structure sharing

slide-71
SLIDE 71

Module Syntax

Bindings Modules Declarations Signatures

B ::= val X=E type X=T module X=M signature X=S include M B;B ǫ D ::= val X:T type X=T type X:K module X:S signature X=S include S D;D ǫ M ::= X {B} M.X fun X:S ⇒M X X X:>S S ::= X {D} M.X (X:S) → S (X:S) ⇒ S S where type X=T

slide-72
SLIDE 72

F-ing Formalisation

slide-73
SLIDE 73

F-ing Elaboration, recap

Signatures Modules Γ ⊢ S ∃α.Σ Γ ⊢ M : ∃α.Σ e

slide-74
SLIDE 74

F-ing Elaboration, recap

Signatures Modules Γ ⊢ S ∃α.Σ Γ ⊢ M : ∃α.Σ e ⇒ Γ ⊢ ∃α.Σ :Ω ⇒ Γ ⊢ e : ∃α.Σ

slide-75
SLIDE 75

Semantic Signatures, recap

(functor) (structure) (type) (term)

Σ ::= [τ] | [= τ:κ] | {l : Σ} | ∀α1.Σ1 → ∃α2.Σ2

slide-76
SLIDE 76

Example: Set Signature

Set : (Elem : ORD) → (SET where type elem = Elem.t) ∀α.{ t : [= α : Ω], leq : [α → α → bool] } → ∃β. { elem : [= α : Ω], set : [= β : Ω], empty : [β], add : [α → β → β], member : [α → β → bool] }

slide-77
SLIDE 77

Elaboration, revised

Signatures Modules Γ ⊢ S ∃α.Σ Γ ⊢ M :ϕ ∃α.Σ e (ϕ ::= P | I)

slide-78
SLIDE 78

Semantic Signatures, revised

(functor) (structure) (type) (term)

Σ ::= [= π:τ] | [= τ:κ] | {l : Σ} | ∀α1.Σ2 →ϕ ∃α2.Σ2

π ::= α τ

(path)

slide-79
SLIDE 79

Semantic Signatures, revised

(functor) (structure) (type) (term) Impure functor: Pure functor:

∀α1.Σ1 →I ∃α2.Σ2 ∃α2.∀α1.Σ1 →P Σ2

Σ ::= [= π:τ] | [= τ:κ] | {l : Σ} | ∀α1.Σ2 →ϕ ∃α2.Σ2

π ::= α τ

(path)

slide-80
SLIDE 80

Functor Signatures

Γ ⊢ S ∃α.Σ

slide-81
SLIDE 81

Functor Signatures

Γ ⊢ S1 ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ S2 ∃α2.Σ2 Γ ⊢ (X:S1) → S2 ∀α1. Σ1 → ∃α2.Σ2 Γ ⊢ S ∃α.Σ

slide-82
SLIDE 82

Functor Signatures

Γ ⊢ S1 ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ S2 ∃α2.Σ2 Γ ⊢ (X:S1) ⇒ S2 ∃α′

2.∀α1. Σ1 → Σ2[α′ 2 α1/α2]

Γ ⊢ S1 ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ S2 ∃α2.Σ2 Γ ⊢ (X:S1) → S2 ∀α1. Σ1 → ∃α2.Σ2

α1 : κ1 α2 : κ2 α′

2 : κ1 → κ2

Γ ⊢ S ∃α.Σ

slide-83
SLIDE 83

Example: Set Signature

Set : (Elem : ORD) ⇒ (SET where type elem = Elem.t) ∃βΩ→Ω. ∀α.{ t : [= α : Ω], leq : [α → α → bool] } → { elem : [= α : Ω], set : [= β α : Ω], empty : [β α], add : [α → β α → β α], member : [α → β α → bool] }

slide-84
SLIDE 84

Example: Set Signature

Set : (Elem : ORD) ⇒ (SET where type elem = Elem.t) ∃β β1β2β3. ∀α α1.{ t : [= α : Ω], leq : [= α1 : α → α → bool] } → { elem : [= α : Ω], set : [= β α α1 : Ω], empty : [= β1 : β α α1], add : [= β2 : α → β α α1 → β α α1], member : [= β3 : α → β α α1 → bool] }

slide-85
SLIDE 85

Functor Expressions

Γ ⊢ M :ϕ ∃α.Σ e

slide-86
SLIDE 86

Functor Expressions

Γ ⊢ M :ϕ ∃α.Σ e Γ ⊢ S ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ M :I ∃α2.Σ2 e Γ ⊢ fun X:S ⇒ M :P ∀α1. Σ1 → ∃α2.Σ2 λα1.λX:Σ1.e

slide-87
SLIDE 87

Functor Expressions

Γ ⊢ M :ϕ ∃α.Σ e Γ ⊢ S ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ M :I ∃α2.Σ2 e Γ ⊢ fun X:S ⇒ M :P ∀α1. Σ1 → ∃α2.Σ2 λα1.λX:Σ1.e Γ ⊢ S ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ M :P ∃α2.Σ2 e Γ ⊢ fun X:S ⇒ M :P ∃α2.∀α1. Σ1 → Σ2 ???

slide-88
SLIDE 88

Elaboration Invariant, revised

Signatures Modules Γ ⊢ S ∃α.Σ ⇒ Γ ⊢ ∃α.Σ :Ω ⇒ Γ ⊢ e : ∃α.Σ Γ ⊢ M :I ∃α.Σ e

slide-89
SLIDE 89

Elaboration Invariant, revised

Signatures Modules Γ ⊢ S ∃α.Σ ⇒ Γ ⊢ ∃α.Σ :Ω ⇒ Γ ⊢ e : ∃α.Σ Γ ⊢ M :I ∃α.Σ e Γ ⊢ M :P ∃α.Σ e

slide-90
SLIDE 90

Elaboration Invariant, revised

Signatures Modules Γ ⊢ S ∃α.Σ ⇒ Γ ⊢ ∃α.Σ :Ω ⇒ Γ ⊢ e : ∃α.Σ Γ ⊢ M :I ∃α.Σ e Γ ⊢ M :P ∃α.Σ e ⇒ · ⊢ e : ∃α.∀Γ.Σ

slide-91
SLIDE 91

Functor Expressions

Γ ⊢ M :ϕ ∃α.Σ e Γ ⊢ S ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ M :I ∃α2.Σ2 e Γ ⊢ fun X:S ⇒ M :P ∀α1. Σ1 → ∃α2.Σ2 λΓ.λα1.λX:Σ1.e Γ ⊢ S ∃α1.Σ1 Γ, α1, X:Σ1 ⊢ M :P ∃α2.Σ2 e Γ ⊢ fun X:S ⇒ M :P ∃α2.∀α1. Σ1 → Σ2 e

slide-92
SLIDE 92

Sealing

Γ ⊢ M :ϕ ∃α.Σ e

α : κ α′ : Γ → κ

Γ(X) = Σ′ Γ ⊢ S ∃α.Σ Γ ⊢ Σ′ ≤ ∃α.Σ ↑ τ f Γ ⊢ X :> S :P ∃α′.Σ[α′ Γ/α] pack λΓ.τ, λΓ.f X

slide-93
SLIDE 93

Elaborating Specifications

slide-94
SLIDE 94

Elaborating Specifications

Γ ⊢ D Ξ

slide-95
SLIDE 95

Elaborating Specifications

Γ ⊢ D Ξ Γ ⊢ K κα Γ ⊢ type X:K ∃α.{X : [= α : κα]}

slide-96
SLIDE 96

Elaborating Specifications

Γ ⊢ T : κ τ Γ ⊢ type X=T {X : [= τ : κ]} Γ ⊢ D Ξ Γ ⊢ K κα Γ ⊢ type X:K ∃α.{X : [= α : κα]}

slide-97
SLIDE 97

Elaborating Specifications

Γ ⊢ T : κ τ Γ ⊢ type X=T {X : [= τ : κ]} Γ ⊢ D Ξ Γ ⊢ K κα Γ ⊢ type X:K ∃α.{X : [= α : κα]} Γ ⊢ T : Ω τ Γ ⊢ val X:T ∃α.{X : [= α : Ω]}

slide-98
SLIDE 98

Elaborating Specifications

Γ ⊢ T : κ τ Γ ⊢ type X=T {X : [= τ : κ]} Γ ⊢ D Ξ Γ ⊢ K κα Γ ⊢ type X:K ∃α.{X : [= α : κα]} Γ ⊢ P : [= π : τ] e Γ ⊢ val X=P {X : [= π : τ]} Γ ⊢ T : Ω τ Γ ⊢ val X:T ∃α.{X : [= α : Ω]}

slide-99
SLIDE 99

Elaborating Bindings

slide-100
SLIDE 100

Elaborating Bindings

Γ ⊢ B : Ξ e

slide-101
SLIDE 101

Elaborating Bindings

Γ ⊢ B : Ξ e Γ ⊢ T : κ τ Γ ⊢ type X=T :ϕ {X : [= τ : κ]} {X = [τ : κ]}

slide-102
SLIDE 102

Elaborating Bindings

Γ ⊢ B : Ξ e Γ ⊢ T : κ τ Γ ⊢ type X=T :ϕ {X : [= τ : κ]} {X = [τ : κ]} Γ ⊢ E : τ e Γ ⊢ val X=E :I ∃α.{X : [= α : τ]} pack {},{X = [e]}

slide-103
SLIDE 103

Elaborating Bindings

Γ ⊢ B : Ξ e Γ ⊢ T : κ τ Γ ⊢ type X=T :ϕ {X : [= τ : κ]} {X = [τ : κ]} Γ ⊢ E : τ e Γ ⊢ val X=E :I ∃α.{X : [= α : τ]} pack {},{X = [e]} Γ ⊢ E : τ e E non-expansive Γ ⊢ val X=E :P ∃α.{X : [= α : τ]} pack λΓ.{}, λΓ.{X = [e]}

slide-104
SLIDE 104

Elaborating Bindings

Γ ⊢ B : Ξ e Γ ⊢ P :ϕ [= π : τ] e Γ ⊢ val X=P :ϕ {X : [= π : τ]} {X = e} Γ ⊢ T : κ τ Γ ⊢ type X=T :ϕ {X : [= τ : κ]} {X = [τ : κ]} Γ ⊢ E : τ e Γ ⊢ val X=E :I ∃α.{X : [= α : τ]} pack {},{X = [e]} Γ ⊢ E : τ e E non-expansive Γ ⊢ val X=E :P ∃α.{X : [= α : τ]} pack λΓ.{}, λΓ.{X = [e]}

slide-105
SLIDE 105

Bonus: Sharing specifications

slide-106
SLIDE 106

Bonus: Sharing specifications

  • paque & transparent value specifications

val x : t vs. val x = A.y

slide-107
SLIDE 107

Bonus: Sharing specifications

  • paque & transparent value specifications

val x : t vs. val x = A.y

  • paque & transparent module specifications

module X : S vs. module X = A.Y

slide-108
SLIDE 108

Bonus: Sharing specifications

  • paque & transparent value specifications

val x : t vs. val x = A.y

  • paque & transparent module specifications

module X : S vs. module X = A.Y value & module refinements S where val X.y = z or S where module X.Y = Z

slide-109
SLIDE 109

Bonus: Sharing specifications

  • paque & transparent value specifications

val x : t vs. val x = A.y

  • paque & transparent module specifications

module X : S vs. module X = A.Y value & module refinements S where val X.y = z or S where module X.Y = Z singleton signatures like X.Y

slide-110
SLIDE 110

Conclusion

slide-111
SLIDE 111

Conclusion

Applicative functors are delicate

slide-112
SLIDE 112

Conclusion

Applicative functors are delicate Applicative ⇔ pure, generative ⇔ impure

slide-113
SLIDE 113

Conclusion

Applicative functors are delicate Applicative ⇔ pure, generative ⇔ impure Module equivalence = type equivalence + value equivalence

slide-114
SLIDE 114

Conclusion

Applicative functors are delicate Applicative ⇔ pure, generative ⇔ impure Module equivalence = type equivalence + value equivalence F-ing modules allows fairly elegant formalisation

slide-115
SLIDE 115

Conclusion

Applicative functors are delicate Applicative ⇔ pure, generative ⇔ impure Module equivalence = type equivalence + value equivalence F-ing modules allows fairly elegant formalisation Gory details in draft article: http://www.mpi-sws.org/~rossberg/f-ing/

slide-116
SLIDE 116

Thank you!

slide-117
SLIDE 117

Outtakes

slide-118
SLIDE 118

Applicative Semantics for Functors is difficult!

Leroy Russo Shao Dreyer+

unrestricted 1st- class modules impure abstraction safe module equivalence no loss of type equivalences

– – – + – –1 + + –2 – – – – + + +

1 Generative functors can be turned applicative after the fact 2 Though you have to try harder

slide-119
SLIDE 119

Example

module Set = fun Elem : ORD ⇒ { type elem = Elem.t type set = list elem val empty = [] val add x s = case s of | [] ⇒ [x] | y :: s' ⇒ if not (Elem.leq x y) then y :: add x s' else if Elem.leq y x then s else x :: s val mem x s = case s of | [] ⇒ false | y :: s' ⇒ Elem.leq y x and (Elem.leq x y or mem x s') } :> SET where type elem = Elem.t