Existential Types (See Chapter 24 of your textbook for reference, but this is not assigned or expected reading) In ML, we can create a module defining a Queue abstract type. The module might have the following interface (ie: signature) and implementation (ie: structure). (*signature*) signature QUEUE = sig type q val empty : q val insert: int -> q -> q val remove: q -> (int * q) option sig (*implementation*) structure Queue :> QUEUE type q = int list val empty = nil fun insert (x, l) = l @ [x] fun remove l = case l of ( nil => None | x::l' => Some (x,l')) end If we want to represent the idea of abstract types, interfaces and implementations in the lambda calculus, we can do that using *existential types.* An existential type has the form (\exists a.t). Existential types will be used to represent signatures. The operations on existential types are *pack* and *unpack*. These operations will be used to represent a very simple form of ML structure (ie: module implementation). For example: type QUEUE = exists q. (q * (int * q -> q) * (q -> (int * q) option)) let Queue = pack [int list, (nil, fun insert (arg: int * int list) : int list = ... fun remove (arg: int list) : (int * int list) option = ... ) ] as QUEUE in unpack q, x = Queue in x.2 (3, x.1) : q ... The Lambda Calculus with existential types ------------------------------------------- Syntax: t ::= ... | exists a.t | a v ::= ... | pack [t, v] as exists a.t' e ::= ... | pack [t, e] as exists a.t' | unpack a, x = e1 in e2 Note: in the (pack[t, e] as exists a. t') expression, t is the concrete "hidden" type and e is the implementation of the module. The type \exists a. t' is the signature. It has an abstract type a in place of the concrete type t. Typing rules: The form of the typing rules is: D; G |- e : t (This is just like the form of the rules for type checking universal types) D |- t D; G |- e : t' [t/a] ----------------------------------------------------- D; G |- pack [t, e] as exists a.t' : exists a.t' D; G |- e1 : exists a.t' D, a; G, x: t' |- e2 : t2 D |- t2 ----------------------------------------------------------------- D; G |- unpack a, x = e1 in e2 : t2 Operational Rules: e1 -> e1' -------------------------------------------------- unpack a, x = e1 in e2 -> unpack a, x = e1' in e2 ------------------------------------------------------------------ unpack a, x = (pack [t, v] as exists a.t') in e2 -> e2[t/a][v/x]