Existential Types Chap 24 Pierce 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 sig (*implementation*) structure Queue :> QUEUE type q = int list val empty = nil fun insert (x, l) = x::l fun remove l = let val x::l' = rev l in (x, rev l') end 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)) let Queue = pack [int list, (nil, fun insert (arg: int * int list) : int list = let (x, l) = arg in (x::l) end fun remove (arg: int list) : (int * int list) = ... ) ] as QUEUE in unpack q, x = Queue in x.2 (3, x.1) : q ... The Lambda Calculus with existential types ------------------------------------------- t ::= ... | \exists 'a.t | 'a e ::= ... | pack [t, e] as \exists 'a. t' (* t is implementation for 'a, e implements the module *) | unpack 'a, x = e1 in e2 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 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]