A Recursive Type System with Type Abbreviations and Abstract Types Keiko Nakata Institute of Cybernetics, Tallinn Joint work with Hyeonseung Im and Sungwoo Park 18 May 2014, Narva-J˜ oesuu
The ML module system The ML module system supports program structuring, code reuse and representation independence (implementation hiding) with - nested structures, - functoros, and - signatures (with abstract types).
Make interval functor module type Comparable = sig type t val compare : t → t → int end module Make interval(Endpoint : Comparable) = struct module E = Endpoint type t = Interval of E.t * E.t | Empty let create low high = ... let is empty = function Empty → true | Interval → false let contains t x = match t with | Empty → false | Interval (l,h) → E.compare x l ≥ 0 and E.compare x h ≤ 0 let intersect t1 t2 = ... end
Instantiating Make interval module Int interval = Make interval(struct type t = int let compare = Int.compare end) let i1 = Int interval.create 3 8 module Rev int interval = Make interval(struct type t = int let compare x y = Int.compare y x end) (* Int interval.t � = Rev int interval.t *) let rev interval = Rev int interval.create 4 3 Int interval.contains rev interval 3
Constraining the result type of functors module type Interval intf = sig type t type endpoint val create : endpoint → endpoint → t val is empty : t → bool val contains : t → endpoint → bool val intersect : t → t → t end module Make interval(Endpoint : Comparable) : (Interval intf with type endpoint = Endpoint.t) = struct module E = Endpoint type endpoint = E.t type t = Interval of E.t * E.t | Empty ... end
Polymorphic recursive types are equi-recursive types: - µ X .τ is equal to its one-step unfolding { X �→ µ X .τ } τ . - Equivalence of equi-recursive types is structural. Principle type infernece is available. Code reuse is archived with structural polymorphism. The module machinery can be combined with polymorphic recursive types, e.g., private types.
Contractiveness A type variable X is contractive in τ , if X occurs in τ only under a type constructor. A recursive type is contractive if every recursive variable is contractive in its scope. In a simple type language, contractiveness can be enforced syntactically τ, σ ::= X | τ → σ | µ X . ( τ → σ ) Contractiveness guarantees the unique solution of recursive equations introduced by equi-recursive types.
Contractiveness in OCaml In an advanced type system, such as in OCaml... Syntactic contractiveness is not sufficient: type ’a t = [‘A of ’a | ‘B];; type s = s t;; We may not be able to know (without breaking type abstraction). module rec M : sig type t end = struct type t = N.t end and N : sig type t end = struct type t = M.t end
Our work A equi-recursive type system with type abbreviations and abstract types. We allow non-contractive types in the implementation, but disallow them in the signature. The type system is proved sound, formalized in Coq.
Non-contractive types in the signature module M : S = struct module type S = sig type ’a t = ’a type ’a t type u = int and v = bool type u = u t and v = v t let f x = x val f : int → u let g x = x val g : v → bool end end let h x = M.g (M.f x) let y = h 3 (* run-time error *) We found the bug together with Jacques Garrigue, which has been fixed in the latest release OCaml 4.00.1.
Type language type constructor type name s , t , u type τ, σ ::= unit base type | α | β | γ type variable | τ → σ function type | τ 1 ∗ τ 2 product type | type application τ t type abbreviation D ::= type α t = τ type equation abbreviation context ∆ ::= · | ∆ , D type variable set Σ ::= · | { α }
Expression language value v ::= () | λ a : τ. e | ( v 1 , v 2 ) term e ::= () | a | x | λ a : τ. e | e 1 e 2 | ( e 1 , e 2 ) | l | fst e | snd e | fix a : τ. e value context Γ ::= · | Γ , x : τ
Module language specification ::= type α t abstract type D | type α t = τ type equation | val l : τ value specification definition d τ ::= type α t = τ type definition d e ::= let l = e value definition signature S ::= · | S , D structure M ::= ( d τ , d e ) program ::= ( M , S , e ) signature sealing P | ( M , e )
Type equivalence The judgment S ⊢ τ ⇀ σ states that type τ unfolds into σ by expanding a type name in τ into its definition under S . ∆ ∋ type α t = σ ∆ ⊢ τ t ⇀ { α �→ τ } σ unfold
Type equivalence R Inductive type equivalence ∆; Σ ⊢ τ 1 = τ 2 α ∈ Σ eq-var eq-unit ∆; Σ ⊢ unit R ∆; Σ ⊢ α R = unit = α ∆; Σ ⊢ τ i R σ i ( i = 1 , 2) ∆; Σ ⊢ τ i R σ i ( i = 1 , 2) eq-fun eq-prod R R ∆; Σ ⊢ τ 1 → τ 2 = σ 1 → σ 2 ∆; Σ ⊢ τ 1 ∗ τ 2 = σ 1 ∗ σ 2 S ∋ type α t S ; Σ ⊢ τ R σ eq-abs S ; Σ ⊢ τ t R = σ t ∆; Σ ⊢ τ ′ R ∆ ⊢ τ ⇀ τ ′ = σ eq-lunfold ∆; Σ ⊢ τ R = σ ∆; Σ ⊢ τ R ∆ ⊢ σ ⇀ σ ′ = σ ′ eq-runfold ∆; Σ ⊢ τ R = σ
Type equivalence R Inductive type equivalence ∆; Σ ⊢ τ 1 = τ 2 α ∈ Σ eq-var eq-unit ∆; Σ ⊢ unit R ∆; Σ ⊢ α R = unit = α ∆; Σ ⊢ τ i R σ i ( i = 1 , 2) ∆; Σ ⊢ τ i R σ i ( i = 1 , 2) eq-fun eq-prod R R ∆; Σ ⊢ τ 1 → τ 2 = σ 1 → σ 2 ∆; Σ ⊢ τ 1 ∗ τ 2 = σ 1 ∗ σ 2 S ∋ type α t S ; Σ ⊢ τ R σ eq-abs S ; Σ ⊢ τ t R = σ t ∆; Σ ⊢ τ ′ R ∆ ⊢ τ ⇀ τ ′ = σ eq-lunfold ∆; Σ ⊢ τ R = σ ∆; Σ ⊢ τ R ∆ ⊢ σ ⇀ σ ′ = σ ′ eq-runfold ∆; Σ ⊢ τ R = σ
Type equivalence ∆; Σ ⊢ τ 1 ≡ τ 2 Coinductive type equivalence ∆; Σ ⊢ τ ≡ = σ ∆; Σ ⊢ τ type ∆; Σ ⊢ σ type eq-ind ∆; Σ ⊢ τ ≡ σ ∆; Σ ⊢ τ type ∆; Σ ⊢ σ type ∆ ⊢ τ ⇀ τ ′ ∆ ⊢ σ ⇀ σ ′ ∆; Σ ⊢ τ ′ ≡ σ ′ eq-coind ∆; Σ ⊢ τ ≡ σ
Contractive types and signatures S ↓ ⇓ τ S ↓ C α ctr-var S ⇓ τ ctr-coind S ↓ C unit ctr-unit ( S , τ ) ∈ C ( S , σ ) ∈ C ( S , τ 1 ) ∈ C ( S , τ 2 ) ∈ C ctr-prod ctr-fun S ↓ C τ → σ S ↓ C τ 1 ∗ τ 2 S ∋ type α t S ↓ C τ S ⊢ τ ⇀ σ S ↓ C σ ctr-type ctr-abs S ↓ C τ t S ↓ C τ BN ( S ) distinct ∀ (type α t = τ ) ∈ S , S ⇓ τ ctr-sig S ⇓
Type soundness of λ rec abs The key lemma in the soundness states that a well-formed type is contractive: Lemma Suppose S ok , S ⇓ , and S ; Σ ⊢ τ type . Then S ⇓ τ . which enables us to prove that type equivalence is preserved by signature elimination: Lemma If S 1 ≦ S 2 , S 2 ⇓ , and S 2 ; Σ ⊢ τ ≡ σ , then S 1 ; Σ ⊢ τ ≡ σ . Theorem The type system for λ rec abs is sound. (We prove the progress and preservation properties.)
Recommend
More recommend