A Type-Theoretic Approach to Higher-Order Modules with Sharing∗

Robert Harper† Mark Lillibridge‡ School of Computer Science Carnegie Mellon University Pittsburgh, PA 15213-3891

Abstract programming idioms; the language may be easily restricted to “second-class” modules found in ML-like languages. The design of a module system for constructing and main- taining large programs is a difficult task that raises a number of theoretical and practical issues. A fundamental issue is 1 Introduction the management of the flow of information between program units at compile time via the notion of an interface. Expe- Modularity is an essential technique for developing and rience has shown that fully opaque interfaces are awkward maintaining large software systems [46, 24, 36]. Most to use in practice since too much information is hidden, and modern programming languages provide some form of that fully transparent interfaces lead to excessive interde- module system that supports the construction of large pendencies, creating problems for maintenance and separate systems from a collection of separately-defined program compilation. The “sharing” specifications of Standard ML units [7, 8, 26, 32]. A fundamental problem is the man- address this issue by allowing the programmer to specify agement of the tension between the need to treat the equational relationships between types in separate modules, but are not expressive enough to allow the programmer com- components of a large system in relative isolation (for plete control over the propagation of type information be- both conceptual and pragmatic reasons) and the need tween modules. to combine these components into a coherent whole. These problems are addressed from a type-theoretic view- In typical cases this problem is addressed by equipping point by considering a calculus based on Girard’s system each module with a well-defined interface that mediates Fω. The calculus differs from those considered in previous all access to the module and requiring that interfaces be studies by relying exclusively on a new form of weak sum enforced at system link time. type to propagate information at compile-time, in contrast The Standard ML (SML) module system [17, 32] to approaches based on strong sums which rely on substi- is a particularly interesting design that has proved to tution. The new form of sum type allows for the specifica- be useful in the development of large software sys- tion of equational, as well as type and kind, information in tems [2, 1, 3, 11, 13]. The main constituents of the interfaces. This provides complete control over the propa- SML module system are signatures, structures, and gation of compile-time information between program units and is sufficient to encode in a straightforward way most functors, with the latter two sometimes called modules. uses of type sharing specifications in Standard ML. Modules A structure is a program unit defining a collection of are treated as “first-class” citizens, and therefore the sys- types, exceptions, values, and structures (known as sub- tem supports higher-order modules and some object-oriented structures of the structure). A functor may be thought of as a “parameterized structure”, a first-order function This∗ work was sponsored by the Advanced Research Projects mapping structures to structures. A signature is an in- Agency, CSTO, under the title “The Fox Project: Advanced De- terface describing the constituents of a structure — the velopment of Systems Software”, ARPA Order No. 8313, issued types, values, exceptions, and structures that it defines, by ESD/AVS under Contract No. F19628–91–C–0168. Electronic† mail address: [email protected]. along with their kinds, types, and interfaces. See Fig- Electronic‡ mail address: [email protected]. ure 1 for an illustrative example of the use of the SML module system; a number of sources are available for further examples and information [15, 39]. A crucial feature of the SML module system is the no- tion of type sharing1 which allows for the specification

1The closely-related notion of structure sharing is not consid- 0 ered in this paper. signature SYMBOL = sig signature LEXER = sig type symbol structure S : SYMBOL val intern : string -> symbol type token val pname : symbol -> string . val eq : symbol * symbol -> bool . end end structure Symbol : SYMBOL = struct signature SYMTAB = sig structure HashTable : HASH TABLE = ... structure S : SYMBOL . type symbol = HashTable.hash key . fun intern id = end HashTable.enter (HashTable.hash id) id signature PARSER = sig fun pname sym = HashTable.retrieve sym structure L : LEXER fun eq (s1, s2) = HashTable.same key s1 s2 val parse : string -> Lexer.token stream end . . end Figure 1: Example of the SML Module System functor Parser (structure L:LEXER and T:SYMTAB of coherence conditions among a collection of structures sharing type L.S.symbol=T.S.symbol):PARSER= that ensure that types defined in separate modules co- struct . incide. The classic example (adapted from MacQueen) . is the construction of a parser from a lexer and a sym- end bol table, each of which make use of a common notion of symbol (see Figure 2). The parser is constructed by Figure 2: Sharing Specifications a functor that takes as arguments two modules, a lexer and a symbol table manager. The parser composes func- tions from the lexer and symbol table manager; the com- signature SIG = sig position is well-typed only if the two modules “share” type t a common notion of symbol. Within the body of the type u functor Parser the types L.S.symbol and T.S.symbol valf:u coincide, as specified by the type sharing specification end in the parameter signature. See MacQueen’s seminal may be correctly ascribed to the structure S without paper for further examples and discussion [26, 17]. obscuring the bindings of S.t and S.u. Functor bindings are similarly “transparent” in that 1.1 Transparency and Opacity the type components of the result of any application of the functor are fully visible within the scope of the Module bindings in SML are “transparent” in the sense functor binding. For example, consider the following that the type components of a module are fully visible functor declaration: in the scope of the binding. For example, the structure functor F(structure X:SIG):SIG = struct declaration type t = X.t * X.t type u = X.u structure S = struct val f = X.f type t = int end type u = t -> t val f = fn x:t => x The bindings of the t and u components of any appli- end cation of F are fully visible as a function of the t and u components of the parameter X. For example, within introduces a structure variable S with type components the scope of the declaration S.t and S.u and value component S.f. Within the structure T:SIG = F(S) scope of S, the type S.t is equivalent to the type int and the type S.u is equivalent to the type int->int. the type T.t is equivalent to the type int*int and the These equivalences are not affected by the ascription of type T.u is equivalent to the type int->int. a signature to the binding. For example, the signature It is possible only to a very limited extent in SML SIG defined by the declaration to specify in a signature the bindings of the types in a module. For example, we may augment the signature determines t, leaving u unconstrained. This signature SIG with a sharing specification to specify that t is int is essentially equivalent to the signature SIG’ above.2 S as follows: matches this signature. signature SIG’ = sig Translucent signatures are particularly useful in con- type t nection with higher-order functors [43]. Using equations sharing type t=int in signatures it is possible to specify the dependency of type u the functor result on the functor argument. For exam- val f : u ple, a natural signature for the functor F defined above end is the following functor signature which fully determines the type components of F: This method cannot be extended to specify the bind- ing of u — sharing specifications may only involve type funsig FULL SIG F= names, not general type expressions. To fully determine (structure X:SIG): the type bindings in S requires a transparent signature: sig type t=X.t*X.t type u=X.u val f:u end signature FULL SIG S = sig Another, less precise, signature for F is the functor sig- type t = int nature type u = int -> int val f : int -> int funsig PARTIAL SIG F= end (structure X:SIG): Note that this is not a legal SML signature because of sig type t type u=X.u val f:u end the type equations. There is no way to express equa- which only specifies the behavior of F on the component tions such as u = int -> int in SML signatures. The u, leaving its behavior on t unspecified. signature FULL SIG S is the “full” signature of S since Higher-order functors [43] are particularly important it completely determines the bindings of its type com- in connection with separate compilation. A separately- ponents. compiled module may be represented by a variable The importance of transparent signatures only be- whose signature is the “full” transparent signature of comes apparent when we consider functors and the the module itself [42]. By abstracting the client mod- closely-related abstraction bindings suggested by ule with respect to these variables we obtain a (possi- MacQueen [26, 17]. Functor parameters are opaque in bly higher-order) functor whose application models the the sense that the ascribed signature is the sole source process of linking the clients of the module with its ac- of type information for those parameters (this property tual implementation. The signature matching process is the basis for the reduction of abstraction bindings ensures that the presumed signature of the separately- to functor applications). Fine control over the “degree” compiled module is consistent with the module itself so of opacity of a functor parameter can be achieved by as to guarantee type safety. The full signature of the admitting transparent, or, more generally, translucent, separately compiled module is necessary to ensure that signatures that allow for the partial (possibly full) de- separate and combined compilation yield the same re- termination of the type components of a module. For sult. example, the translucent signature signature PARTIAL SIG S 1 = sig 1.2 Static Semantics type t type u = t -> t The static semantics of SML [32] is defined by a col- val f : u lection of complex elaboration rules that specify the end static well-formedness conditions for SML programs. The main techniques employed in the semantics are the is a partially transparent signature that leaves the type use of “unique names” (or “generativity”) to handle t unconstrained, but determines u up to the choice of t. abstraction and sharing specifications, and the use of The structure S matches the signature PARTIAL SIG S 1 non-deterministic rules to handle polymorphism, shar- since S.u is equal to S.t->S.t which is itself equal to ing specifications, and signature matching. The static int->int. Conversely, the translucent signature semantics has proved useful as a guide to implementa- signature PARTIAL SIG S 2 = sig tion [28, 2, 41, 40], but is remarkably difficult to modify

type t = int 2 type u It seems plausible that most uses of type sharing specifications may be accounted for in this way, provided that we neglect local val f : u specifications and re-binding of variables in specifications, both of end which are of questionable utility.  or extend (see, for example, [43]). The na¨ıve attempt to Kinds K ::= Ω | K⇒K enrich signatures as sketched above is incompatible with A α | x A.A |{D ,...,D }| the crucial “principal signature” property [31]. But it is Constructors ::= Π : 1 n λα::K.A | AA | V.b not clear whether this failure is a symptom of an intrin- Declarations D ::= b α::K | b α::K=A | y x:A sic incoherence in the language, or is merely an artifact 3 of the semantic method. Terms M ::= x | λx:A.M | MM | M:A | In an effort to gain some insight into the complexi- {B1,...,Bn}|M.y ties of the static semantics several authors have under- Bindings B ::= b α=A | y x=M taken a type-theoretic analysis of SML, especially its module system [27, 33, 35, 7, 20, 19]. Previous studies Values V ::= x | λx:A.M |{Bv1,...,Bvn}| of the module system focused on the transparency of V.y SML-style structures through the use of “strong sum” Bv ::= b α=A | y x=V or “dependent product” types. These are types of the Contexts Γ ::= •|Γ,α::K | Γ,α::K=A | Γ,x:A form Σx:A.B(x) whose elements are pairs M1,M2 that are accessed via projections π1(M) and π2(M). Figure 3: Syntax rules (n ≥ 0) The crucial properties of strong sums [29] are that if M :Σx:A.B(x), then π2(M):B(π1(M)), and that π1(M1,M2)=M1. Together, these properties ensure type information at compile time so that we can achieve that type information is propagated in rough accord the effect of SML-like sharing specifications and provide with the SML static semantics. (See [27, 33, 20, 19] direct support for abstraction. for further discussion.) Substitution-based methods are problematic in the presence of computational effects, unless care is taken to account for the phase distinc- 2 Overview of the Calculus tion [20]. Moreover, strong sums fail to account for sharing specifications and the abstract nature (“gener- Our system is based on Girard’s Fω [14] in much the ativity”) of structure and datatype bindings. same way that many systems are based on the second- In this paper we extend the type-theoretic analysis of order lambda calculus (F2). That is to say, our system SML-like module systems by presenting a calculus with can be (roughly) thought of as being obtained from Fω the following features: by adding more powerful constructs (translucent sums and dependent functions) and a notion of subtyping and • 4 Translucent sum types, which generalize weak sums then removing the old constructs (quantification (∀), by providing labeled fields and equations governing weak sums (∃), and non-dependent functions (→)) su- type constructors. These mechanisms obviate the perseded by the new ones. Subtyping interacts with the need for substitution, and account for abstraction rest of the calculus via implicit subsumption. Bounded and common uses of SML-style sharing specifica- quantification is not supported. tions. Like Fω, our system is divided into three levels: terms, (type) constructors, and kinds. Kinds classify • A notion of subsumption that encompasses a “co- constructors, and a subset of constructors, called types, ercive” pre-order associated with record fields and having kind Ω classify terms. The kind level is neces- a “forgetful” pre-order associated with equations sary because the constructor level contains functions on that represent sharing information. constructors. Example: the constructor λα::Ω.α→α has ⇒ → • Treatment of modules as “first-class” values. The kind Ω Ω and when applied to type Int yields Int Int. typing rules ensure that visibility of compile-time The syntax rules for our system are given in Figure 3. components is suitably restricted when run-time se- The meta variable α ranges over constructor variables lection is used (see also [34]). If run-time selection and the meta variable x ranges over term variables. The is not used, modules behave exactly as they would meta variable b ranges over constructor field names and in a more familiar “second-class” module system the meta variable y ranges over term field names.We such as is found in SML. 4 Quantification is derivable from dependent functions and translucent sums. The basic idea is to transform Λα::K. M into Our calculus improves on previous work by providing a λx:{b α::K}. [x.b/α]M where x is not free in M and M [A]into much greater degree of control over the propagation of M {b α=A}. Note that this implements constructor abstraction as a delaying operation unlike the normal SML semantics. See [16] 3Based on the approach taken here, and a related idea due to for a discussion of the differences between these two interpreta- Leroy, Tofte has recently devised a way to accommodate a form tions of constructor abstractions and why this choice seems to be of type abbreviation in Standard MLs ignatures [44]. preferable. have placed field names in bold in order to help empha- values (V ) are considered to be term variables, term size that they are names, not variables. The complete λ-expressions, translucent sums containing only values typing rules appear in appendix A. and constructors, and selections of term fields from val- Our handling of dependent functions (λx:A.M)is ues. We allow V.y to be a value in order to allow paths standard [29] except that our elimination rule only al- like x.y.y to be values while still keeping the set of val- lows for the application of functions having arrow-types5 ues closed under the substitution of a value for a term (non-dependent function types). The normal elimina- variable. tion rule for dependent functions does not have this re- striction, requiring functions only to have a Π-type. We make this restriction because we intend to extend this 3 Translucent Sums system in future work with effect-producing primitives. A translucent sum has the form of a possibly empty In the presence of effects, the unrestricted rule is un- sequence of bindings written between curly braces sound because of interactions with the first-class nature 6 ({B1,...,Bn}). The corresponding translucent sum of translucent sums. type is similar except that declarations are used instead Translucent sums ({B1,...,Bn}), the central contri- of bindings ({D1,...,Dn}). bution of the calculus, will be discussed at length in Translucent sums differ from traditional records in the next section. Very briefly, they are n-ary labeled a number of ways. In addition to normal term fields, dependent sums whose types can optionally contain in- they can contain constructor fields. The type or content formation about the contents of their constructor fields. of later fields in a translucent sum can depend on the Traditional records and weak sums (existentials) are de- content of earlier fields. As an example, consider the generate forms of translucent sums. following translucent sum, call it P , that packages up a A mechanism (written M:A) for forcing a term M to type with a value of that type:9 be coerced to a supertype A is provided. The subtyp- ing relation allows for both generalized record subtyp- {b α=Int, y x=3} : {b α::Ω, y x:α} ing [7, 6, 9] (fields which are not depended on by the 10 Binding r to P would give r.b :: Ω and r.y : r.b. other fields in a translucent sum may be dropped) and The scope of variables bound in bindings and decla- for the forgetting of information about the contents of rations is all the following bindings/declarations in that constructor fields. translucent sum (type). For example, the scope of x in There are two basic forms of constructor definitions. the following translucent sum includes M and A but A constructor definition is opaque if within the scope not M or A: of the definition there is no information available about       the identity of the constructor variable being defined. {b α=A, y x=M, y x=M , b α=A } By contrast, a transparent constructor definition makes Scoping for the other constructs is as normal. We re- available the identity of the constructor variable that is gard terms, constructors, etc., that differ only by α- being defined. conversion of variables as equivalent. Contexts in our system can contain both opaque α α K α K A Note that field names cannot be -converted. Chang- ( :: ) and transparent ( :: = ) definitions. The ef- ing a field name in a translucent sum term/type results fect of transparency is implemented by a typing rule in a different term/type because the set of legal field (ABBREV’) for the constructor equality relation judge- α A α K A names which can be selected changes. Failure to distin- ment that establishes that = when :: = is in guish between field names which cannot be α-converted the context. (This is similar to mechanisms used in AU- and the internal names for fields which must be able TOMATH and LEGO [12, 45, 25].) to α-convert in order to permit substitution to work, Our calculus is intended to be interpreted using a call- leads to problems.11 For example, the equivalent of the by-value semantics. The typing system is not sound for call-by-name in the presence of effects.7 We re- would be that useful anyway since the substitution of general terms for term variables would be prohibited in a call-by-value strict terms in constructors to values in order to avoid setting in any case. the problem of trying to give a meaning to a construc- 9We suggest pronouncing “” as “as”, “:” as “has type”, and 8 tor containing a side-effecting term. In our system, “::” as “has kind”. 10Note the distinction between r and P here: r is a term vari- 5The arrow-type A→A can be regarded as an abbreviation for able (and hence a value) while P is a term meta-variable denot- Πx:A.A where x is not free in A. ing a non-value. This distinction is important because the typing 6Abbreviated example: (((λx. x.y)M).2) (((λx. x.y)M).1) rules treat values specially. where M is the example in section 4.6. 11To avoid verbosity, a real based on 7To see this consider the outermost β-redex of (λx.(x.y.2) our system would probably provide that by default only one name (x.y.1)) M where M is the example in section 4.6. need be given per field, to be used as both the field name and the 8It is not clear that allowing general terms in constructors internal name. following cannot be written straightforwardly in SML:12 checking later bindings and in the resulting type. Thus, the introduction rule gives P the more expressive type. {b α=Int, y x={b α=Bool, y x=λx:α. 3}} :     The less-expressive type is obtained by the use of the {b α::Ω, y x:{b α::Ω, y x:α →α}} subsumption rule afterwards. Because SML does not distinguish the two kinds of There are two elimination forms with corresponding names, it is problematic to express that the type of the rules for translucent sums, one for constructor fields and y field depends on both the outer and inner b fields. one for term fields: The field names of any given translucent sum (type) Γ  V : {b α::K} are required to be distinct. Translucent sum types that (C-EXT-O) Γ  V.b :: K differ only in that their declarations have been reordered without violating any dependences are considered equiv- Γ  M : {y x:A} alent. For example, the following first two types are (EXT-V) equivalent but both are different from the third type: Γ  M.y : A In order to apply these rules to translucent sums with {b α::Ω, b1 α1::Ω=α, b2 α2::Ω=α} multiple fields, it is first necessary to use the subsump- {b α::Ω, b2 α2::Ω=α, b1 α1::Ω=α} {b1 α1::Ω=α, b α::Ω, b2 α2::Ω=α} tion rule to drop the fields that are not being selected. The constructor field case may also require that type It may help to think of translucent sum types as be- information about the field to be selected be dropped. ing directed acyclic graphs (DAGs) where the nodes are Unlike traditional records, with translucent sums it is declarations and the edges are dependencies by one dec- not always possible to drop all the other fields because laration on a variable declared in another declaration. the field we wish to select may depend in an essential It is possible to include information in a translucent way on them. Thus, the fact that M has a translucent sum type on the contents of the constructor fields of sum type with a y field is not in itself sufficient to en- its instances. This ability can be used to give a more sure that M.y is well-typed.13 It is always possible to expressive type to P : drop fields from the type of V because of the VALUE rules which we will discuss in section 3.3. {b α=Int, y x=3} : {b α::Ω=Int, y x:α} r If it can be shown that has this type, then it can be 3.2 Translucency inferred that r.b = Int. This can not be inferred if it can only be shown that r has the less expressive type. When x:A appears in the context where A is a translu- The use of nested translucent sums and constructor field cent sum type which contains information about the component information can give rise to more complex contents of the constructor fields of its instances, it gives dependencies as the following example illustrates: rise to equations via the following rule:

  {y x={b α=Int}, y x=3, b α=x.b} : Γ  V : {b α::K=A} { x{ α },  x x. , α x. } (ABBREV) y : b ::Ω y : b b ::Ω= b Γ  V.b = A :: K

3.1 Introduction and elimination rules Thus it is possible to infer that r.b = Int when it can be shown that r has the type ({b α::Ω=Int, y x:α}) The introduction rule for translucent sums is as follows: but not when it can only be shown to have the type  Γ valid ({b α::Ω, y x:α}).

∀i ∈ [1..n]. Γ, D1,...,Di−1  Bi : Di This rule also gives rise to equations such as (TSUM) {b α=Int, b α=Bool}.b =Bool. These equations Γ {B1,...,Bn} : {D1,...,Dn} allow any valid constructor V.b to be reduced to a (The overline function (D) merely strips off the field constructor which contains only values of the form name.) Note that each of the bindings is being type x.y1 ···.yn (n ≥ 0). Because of this, it is not neces- checked under a context which takes account of the ef- sary in our system to consider the equality of arbitrary fect of all of the previous bindings. Constructor bind- values (and hence terms) at type-checking time. ings result in transparent definitions, both when type When the equality rules compare the parts of a con- 12 structor that are in the scope of a variable binding, they It is possible to write this in SML by using a combination of local specifications and type sharing in the signature. Thanks to do so with the declaration associated with that vari- Mads Tofte for pointing this out. Unfortunately, however, some able in the context. For example, the equality rule for SML implementations (e.g., SML/NJ) do not implement local specifications in signatures properly so this is not very helpful in 13For example, ({b α=Int, y x=3} : {b α::Ω, practice. y x:α}).y is not well-typed. Π-types below compares A1 and A2 with x:A1 in the 3.3 The VALUE rules context: Suppose the typing context contains the following dec- Γ  A1 = A2 :: Ω laration:   Γ,x:A1  A1 = A2 :: Ω (E-DFUN) r:{b α::Ω, y x:α}   Γ  Πx:A1.A1 =Πx:A2.A2 :: Ω What types can we give to the expression r under this This allows use of the ABBREV rule to obtain equa- context? Because we have a name, r, for the translucent tions such as the following: sum expression we are trying to type, we have a name for the contents of its b field, namely r.b. This sug- Πx:{b α::Ω=Int}.x.b =Πx:{b α::Ω=Int}. Int gests that we can give r the type {b α::Ω=r.b, y x:r.b} {b α::Ω=Int, y x:α} = {b α::Ω=Int, y x:Int} which is a subtype of the context type for r. This technique of giving a more expressive type to A similar effect occurs while typing terms. For exam- translucent sums when we have a name for their con- ple, in the following, we know that x.b = Int while type structor components can be generalized to work on ar- checking M: bitrary translucent sum values. The name in this case is simply V.b where V is the value in question. Attempt- { x{ α },  x M} ing to extend the technique to general terms requires y : b ::Ω=Int y : dropping the restriction that only values may appear in constructors and results in unsoundness in the presence Because of the ability to substitute away transparently of effects.14 The following two typing rules implement bound names using the equality rules, no dependency this technique: on a transparently bound name is ever truly essential.

This allows many more field selections and function ap- Γ  V : {b α::K,D1,...,Dn} plications to type check than would otherwise be the (VALUE-O) Γ  V : {b α::K=V.b,D1,...,Dn} case. When translucent sums are given fully opaque types, they act like weak sums which can be used to create Γ  V.y : A abstract data types (ADTs) [35]. Because we have de- Γ  V : {y x:A, D1,...,Dn} (VALUE-V) pendent functions and a form of dependent pairs (a pair  Γ  V : {y x:A ,D1,...,Dn} of terms where the type of the second term depends on the first component of the pair), our elimination form (The VALUE-V rule is used in cases of nested translu- for weak sums is more powerful than usual [35, 7, 10]. cent sums to apply the technique recursively.) Consider the following example in SML-like notation, By alternately applying the VALUE rules to convert where weak is used to construct a weak sum: an opaque binding into a transparent one and the sub- sumption rule to propagate that definition (and hence let structure S = struct removing any dependencies on that binding), we can structure Stack = weak give any translucent sum value a fully transparent type type T = (int ref) list (there are no constructor components for which infor- val makeStack:()->T = ... mation is lacking) with no dependencies between the val push:(int,T)->() = ... fields (or subfields). Because of this, field selection on ... values as well as applications of functions to values do end not run into problems due to the inability to remove de- val myStack = Stack.makeStack() pendencies. Without this kind of usage of the VALUE end in rules, expressions such as r.y would not type check. S.Stack.push(1,S.myStack) The more expressive type given by the VALUE rules end to translucent sum values is also critical to the propaga- tion of typing information. For example, if s is bound to This example is well-typed in our system because we can the result of the expression r, it will be given the more determine that S.myStack has type S.Stack.T which is expressive type, allowing the fact that s.b = r.b to be the argument type of the function S.Stack.push. Note inferred. that there is no way to type this example using the open elimination form for weak sums because there is 14 This would allow field selection to always succeed because no scope containing both the initialization of myStack it would permit all dependencies to be removed. Unsoundness and its use that is also inside the scope of Stack. example: (M.y.2) (M.y.1) where M is the example in section 4.6. 4 Selected Examples have been as if we had given S in our system the signa- ture SIG. That is to say, S.t and S.u would have been 4.1 Simple structures bound opaquely. Note that it is not possible in SML/NJ to give S a partial signature using this mechanism. Only Typical SML structures can be translated straightfor- the fully transparent (via structure) and fully opaque wardly into our system, with the only complication (via abstraction) alternatives are available. being the treatment of polymorphism (as discussed Abstraction bindings can be translated into our sys- in [16].) Consider the following structure considered S tem by inserting a forced coercion just before the bind- in the introduction: ing to the appropriate opaque type. For example, con- structure S = struct sider the following implementation of an abstract data type t = int type (ADT): type u = t -> t abstraction Stack = struct val f = fn x:t => x type T = (int ref) list end val push:(T,int)->() = ... val pop:T->int = ... This translates as: val isEmpty:T->bool = ... S = {t  t=Int, u  u=t→t, f  f=λx:t. x} end This translates to: The translations of the signatures considered earlier {  , (only SIG here is actually a valid SML signature) are: Stack =( T T=list(ref Int) push  push=(...):(T, Int)→(), FULL SIG S = {t  t::Ω=Int, u  u::Ω=Int→Int, pop  pop=(...):T→Int, f  f:Int→Int} isEmpty  isEmpty=(...):T→Bool } PARTIAL SIG S 1 = {t  t::Ω, u  u::Ω=t→t, f  f:u} ):{ T  T::Ω, PARTIAL SIG S 2 = {t  t::Ω=Int, u  u::Ω, f  f:u} push  push:(T, Int)→(), SIG = {t  t::Ω, u  u::Ω, f  f:u} pop  pop:T→Int, isEmpty  isEmpty:T→Bool } The subtyping rules for our system establish that Note that because the type information about the iden- FULL SIG S ≤ PARTIAL SIG S 1 ≤ SIG and tity of the T field is lost in the coercion, the rest of FULL SIG S ≤ PARTIAL SIG S 2 ≤ SIG. The signatures the program will be unable to break the abstraction. PARTIAL SIG S 1 and PARTIAL SIG S 2 are incompara- SML provides an abstraction mechanism, abstype, at the ble. core language level. Because translucent sums are first- The signature given to S determines which equations class in our system, we can achieve the effect of SML’s on S.t and S.u can be deduced. By default our system, abstype using the abstraction binding mechanism. like SML, will give S its full signature, FULL SIG S. This means that we will be able to deduce that S.t =Int and S.u =Int→Int. If we insert a coercion to one of the 4.3 Sub-structures other signatures before the binding to S, fewer equations Sub-structures are also easily translated. For example, will be deducable in our system. In SML, by contrast, suppose we wanted to use the Stack structure in a bigger user-specified coercions never result in the loss of typing structure as follows: information. They can, however, result in the loss of fields. Thus, in order to translate a coercion from SML structure Big = struct into our system, we need to enrich the target signature structure ourStack = Stack with all the available typing information. type T = ourStack.T ... end 4.2 Abstraction This translates into: SML/NJ [2] supports an extension to SML, called ab- Big = {ourStack  ourStack=Stack, T  T=ourStack.T, ...} straction, which is an alternative to the normal struc- ture binding mechanism. If the keyword abstraction Big will be given the following full signature: is used instead of the keyword when bind- structure {ourStack  ourStack:{ T  T::Ω=Stack.T, ing a structure, all information about the constructor push  push:(T, Int)→(), components of that structure is forgotten. Had S in pop  pop:T→Int, the previous example been bound with an abstraction isEmpty  isEmpty:T→Bool }, binding instead of the structure one we used, it would T  T::Ω=ourStack.T,...} Note that we have that Big.ourStack.T = Big.T = signature H = sig Stack.T. type t type u 4.4 Functors type v sharing type t = u Functors translate into dependent functions in the ex- and type v = u pected way. Consider the following example from the end introduction: translates into: functor F(structure X:SIG):SIG = struct type t = X.t * X.t H = {t  t::Ω, u  u::Ω=t, v  v::Ω=t} type u = X.u val f = X.f A more interesting case is provided by the argument end signature of the Parser functor in MacQueen’s example from the introduction: This translates into: sig structure L:LEXER F = λX:SIG. ( {t  t=X.t ∗ X.t, u  u=X.u, f  f=X.f} : {t  t::Ω=X.t ∗ X.t, u  u::Ω=X.u, f  f:u}) structure T:SYMTAB sharing type L.S.symbol=T.S.symbol (The coercion on the result type of the functor is an end abbreviation for a coercion on the functor body.) Note the enriched signature we have to give instead of SIG This translates into: in order to make the coercion have the same effect as {L  L:LEXER, T  T:{S  S:{symbol  symbol::Ω=L.S.symbol, it does in SML. Translating the functor signatures we ...},...}} considered for F gives: The omitted parts are the usual translation of the rest . {  . ∗ . ,  . , FULL SIG F =ΠX:SIG t t::Ω=X t X t u u::Ω=X u of SYMTAB and SYMBOL. This translation method also  : } f f u works on sharing between constructors in the argument PARTIAL SIG F =ΠX:SIG. {t  t::Ω, u  u::Ω=X.u, f  f:u} and result of a functor. SIG F =ΠX:SIG. SIG ≤ ≤ Here, FULL SIG F PARTIAL SIG F SIG F. 4.6 First-class modules Suppose T was bound to the result of applying F to S. Before the APP rule can be applied to determine So long as we restrict ourselves to simple module op- T’s type, the subsumption rule must be used to co- erations like binding, functor application of a named erce F’s type (FULL SIG F) to an arrow type. One way functor to a named or fully transparent module, and se- this could be done is shown in Figure 4. First, F’s ar- lection from a named module, we never lose any typing gument type is coerced to a subtype (remember that information. In fact, the only module operation avail- FULL SIG S ≤ SIG) using the fact that subtyping of able in SML that causes a loss of information when used function types is contra-variant. Next, the equality rules in our system is coercing a module to a user-specified are used to remove the dependencies on X by the result type. This is not surprising, however, since the purpose type, resulting in an arrow type. The result is that T of coercions is controlled information loss. gets assigned the following type: Due to the fact that modules are first-class in our system, it is possible to write module expressions which {t  t::Ω=Int ∗ Int, u  u::Ω=Int→Int, f  f:u} force the loss of typing information in order to preserve If F had instead had the type PARTIAL SIG F, T would soundness. For example, consider the following:15 have been assigned the type: if flip() then {b α=Int, y x=(3, succ)} {t  t::Ω, u  u::Ω=Int→Int, f  f:u} else {b α=Bool, y x=(true, not)}

4.5 Sharing specifications While both parts of the if can be given fully transpar- ent types, these types are not equal. In order to make The basic idea in translating sharing specifications is the if type check, we must give them equal types. The that for each set of names that are asserted to be equal, only way to do this is to use the subsumption rule to pick one with maximal scope as representative of the coerce both of their types to {b α::Ω, y x:(α, α→α)}. equivalence class and set the others equal to it using 15For the unsoundness examples, flip is a function which al- transparent definitions. For example, the following SML ternates returning true and false. It is easily implemented using signature: a global variable. FULL SIG F =ΠX:SIG. {t  t::Ω=X.t ∗ X.t, u  u::Ω=X.u, f  f:u} ≤ ΠX:FULL SIG S. {t  t::Ω=X.t ∗ X.t, u  u::Ω=X.u, f  f:u} =ΠX:{t  t::Ω=Int, u  u::Ω=Int→Int, f  f:Int→Int}. {t  t::Ω=X.t ∗ X.t, u  u::Ω=X.u, f  f:u} =ΠX:{t  t::Ω=Int, u  u::Ω=Int→Int, f  f:Int→Int}. {t  t::Ω=Int ∗ Int, u  u::Ω=Int→Int, f  f:u} = FULL SIG S→{t  t::Ω=Int ∗ Int, u  u::Ω=Int→Int, f  f:u}

Figure 4: Steps in coercing F’s type to an arrow type

The system described in [34] displays similar behav- Mitchell, et al. [34] consider an extension of the SML ior, namely a forced loss of typing information when module system with first-class modules as a means using modules in conditionals and other primitives. In of supporting certain object-oriented programming id- that system, types are divided into two universes, U1, ioms. Their paper is primarily concerned with illustrat- the universe of “normal” types like Int and Bool→Int, ing an interesting language design rather than with the and U2, the universe of module types. The loss in this type-theoretic underpinnings of such a language, though system is caused by the need to apply an implicit co- a brief sketch is provided. A comparison with their work ercion from a strong sum (which belongs to U2)toa is given in Section 4.6. weak sum (which belongs to U1) because primitives op- The type-theoretic analysis of the SML modules sys- erate only on terms with types in U1. This coercion tem was initiated by MacQueen [27], and further devel- causes a total loss of typing information. Our system is oped by Harper and Mitchell [33, 20, 19]. This work is more flexible than this because it only loses just enough summarized and compared with the present work in the information to ensure soundness. introduction. The possible uses for first-class modules have not been Our language bears some relationship to Russell [4] well explored. One known use discussed in [35] is to and Poly [30], but a detailed comparison seems diffi- select at runtime between two or more ADTs which im- cult in the absence of a type-theoretic analysis of these plement the same abstraction using different algorithms languages (see [21] for an early attempt). based on expected usage conditions. For example, we In an effort to address the problem of separate compi- could use one particular hash table implementation for lation, Leroy has independently developed a variant of small tables and another for large ones. the SML modules system based on the notion of a “man- ifest type” which is similar in spirit to our translucent sum types. See Leroy’s paper in this volume [23] for 5 Related Work a description of his system and some comments on its relationship to ours. An early influential attempt to give a comprehensive type-theoretic analysis of modularity and abstraction was undertaken by Burstall and Lampson with the ex- 6 Conclusions perimental language Pebble [5]. Their work stresses the role of dependent types and the mechanisms required to The main contribution of this work is the design of a support abstraction, but does not address the problem calculus of modularity with the following features: of controlling the “degree” of abstraction. In particu- lar, Pebble supports type and value bindings as primi- • Fine control over the “degree” of abstraction tive notions, but with an “opaque” typing discipline, in through the notion of a translucent sum type. contrast to our calculus. Cardelli’s language Quest [7] has exerted a strong • A treatment of modules as first-class entities with- influence on the present work. Our approach shares out sacrificing the control over type abstraction af- with Quest the emphasis on type-theoretic methods, forded by a second-class module system. and is similarly based on Girard’s Fω enriched with a no- tion of subsumption (though we depart from Cardelli’s • Support for separate compilation in a form that approach by omitting bounded quantification). Quest ensures the complete equivalence between separate does not provide an adequate treatment of modularity; and integrated compilation of a large system. our work can be seen as providing the type-theoretic ba- sis for an extension of Quest with an expressive module The following are some important directions for fu- system. ture research: • Establish the soundness of the type system by prov- [8] Luca Cardelli, James Donahue, Lucille Glassman, Mick ing preservation of typing under a call-by-value op- Jordan, Bill Kalsow, and Greg Nelson. Modula-3 report erational semantics. (revised). Technical Report 52, DEC Systems Research Center, Palo Alto, CA, November 1989. • Investigate the efficiency of type checking and de- [9] Luca Cardelli and Peter Wegner. On understanding velop practical algorithms that may be used in an types, data abstraction, and polymorphism. Computing implementation. We show in Appendix B that the Surveys, 18(4), December 1986. subtyping problem for our system, and hence the [10] Luca Cardelli and Leroy Xavier. Abstract types and type checking problem, is undecidable. There is the dot notation. Technical Report 56, DEC SRC, Palo reason to believe, however, that this will not be a Alto, CA, March 1990. problem in practice. [11] Eric Cooper, Robert Harper, and Peter Lee. The Fox • Design an elaborator to translate an SML-like syn- project: Advanced development of systems software. tax into the calculus, including a systematic treat- Technical Report CMU–CS–91–178, School of Com- ment of the reduction of symmetric sharing spec- puter Science, Carnegie Mellon University, Pittsburgh, PA, August 1991. ifications to asymmetric definitions in signatures. [12] Nicolas G. de Bruijn. A survey of the project AU- • Develop an treatment of structure sharing that ac- TOMATH. In J. P. Seldin and J. R. Hindley, edi- counts for structure generativity and interacts well tors, To H. B. Curry: Essays in Combinatory Logic, with computational effects. Lambda Calculus and Formalism, pages 589–606. Aca- demic Press, 1980. [13] Emden Gansner and John Reppy. eXene. In Robert Acknowledgements Harper, editor, Third International Workshop on Stan- dard ML, Pittsburgh, PA, September 1991. School of We are grateful to Andrew Appel, Luca Cardelli, Olivier Computer Science, Carnegie Mellon University. Danvy, John Greiner, Nick Haines, Mark Leone, Xavier [14] Jean-Yves Girard. Interpr´etation Fonctionnelle et Leroy, Brian Milnes, John Mitchell, and Mads Tofte for Elimination´ des Coupures dans l’Arithm´etique d’Ordre their comments and suggestions. Sup´erieure. PhD thesis, Universit´e Paris VII, 1972. [15] Robert Harper. Introduction to Standard ML. Techni- References cal Report ECS–LFCS–86–14, Laboratory for the Foun- dations of Computer Science, Edinburgh University, [1] Andrew W. Appel. Compiling with Continuations. September 1986. Cambridge University Press, 1992. [16] Robert Harper and Mark Lillibridge. Explicit polymor- [2] Andrew W. Appel and David B. MacQueen. Standard phism and CPS conversion. In Twentieth ACM Sympo- ML of New Jersey. In J. Maluszynski and M. Wirsing, sium on Principles of Programming Languages, pages editors, Third Int’l Symp. on Prog. Lang. Implementa- 206–219, Charleston, SC, January 1993. ACM, ACM. tion and Logic Programming, pages 1–13, New York, [17] Robert Harper, David MacQueen, and . August 1991. Springer-Verlag. Standard ML. Technical Report ECS–LFCS–86–2, Lab- [3] Edoardo Biagioni, Nicholas Haines, Robert Harper, Pe- oratory for the Foundations of Computer Science, Ed- ter Lee, Brian G. Milnes, and Eliot B. Moss. ML signa- inburgh University, March 1986. tures for a protocol stack. Fox Memorandum CMU–CS– [18] Robert Harper, David MacQueen, and Robin Milner. 93–170, School of Computer Science, Carnegie Mellon Standard ML. Technical Report ECS–LFCS–86–2, Lab- University, Pittsburgh, PA, July 1993. oratory for the Foundations of Computer Science, Ed- [4] Hans-J¨urgen B¨ohm, Alan Demers, and James Donahue. inburgh University, March 1986. An informal description of Russell. Technical Report [19] Robert Harper and John C. Mitchell. On the type 80–430, Computer Science Department, Cornell Uni- structure of Standard ML. ACM Transactions on versity, Ithaca, New York, 1980. Programming Languages and Systems, 15(2):211–252, [5] Rod Burstall and Butler Lampson. A kernel language April 1993. (See also [33].). for abstract data types and modules. In Kahn et al. [20] Robert Harper, John C. Mitchell, and Eugenio Moggi. [22], pages 1–50. Higher-order modules and the phase distinction. In Sev- [6] Luca Cardelli. A semantics of multiple inheritance. In enteenth ACM Symposium on Principles of Program- Kahn et al. [22], pages 51–67. ming Languages, San Francisco, CA, January 1990. [7] Luca Cardelli. Typeful programming. Technical Re- [21] James G. Hook. Understanding russell: A first attempt. port 45, DEC SRC, 1989. In Kahn et al. [22], pages 69–85. [22] Gilles Kahn, David MacQueen, and Gordon Plotkin, [38] Benjamin C. Pierce. Programming with Intersec- editors. Semantics of Data Types, volume 173 of Lec- tion Types and Bounded Polymorphism. PhD thesis, ture Notes in Computer Science. Springer-Verlag, June School of Computer Science, Carnegie Mellon Univer- 1984. sity, Pittsburgh, PA, December 1991. [23] Xavier Leroy. Manifest types, modules, and separate [39] Chris Reade. Elements of . In- compilation. In Proceedings of the Twenty-first Annual ternational Computer Science Series. Addison Wesley, ACM Symposium on Principles of Programming Lan- 1989. guages, Portland. ACM, January 1994. [40] Nick Rothwell. Functional compilation from the Stan- [24] Barbara Liskov and John Guttag. Abstraction and Spec- dard ML core language to lambda calculus. Technical ification in Program Development. MIT Press, 1986. Report ECS–LFCS–92–235, Laboratory for the Foun- [25] Zhaolui Luo, Robert Pollack, and Paul Taylor. How dations of Computer Science, Edinburgh University, to use Lego: A preliminary user’s manual. Technical Edinburgh, Scotland, September 1992. Report LFCS-TN-27, Laboratory for the Foundations [41] Nick Rothwell. Miscellaneous design issues in the ML of Computer Science, Edinburgh University, October kit. Technical Report ECS–LFCS–92–237, Laboratory 1989. for the Foundations of Computer Science, Edinburgh [26] David MacQueen. Modules for Standard ML. In 1984 University, Edinburgh, Scotland, September 1992. ACM Conference on LISP and Functional Program- [42] Zhong Shao and Andrew Appel. Smartest recompi- ming, pages 198–207, 1984. Revised version appears lation. In Twentieth ACM Symposium on Principles in [18]. of Programming Languages, pages 439–450, Charleston, [27] David MacQueen. Using dependent types to express SC, January 1993. modular structure. In Thirteenth ACM Symposium on [43] Mads Tofte. Principal signatures for higher-order pro- Principles of Programming Languages, 1986. gram modules. In Nineteenth ACM Symposium on [28] David B. MacQueen. An implementation of Standard Principles of Programming Languages, pages 189–199, ML modules. In Proceedings of the 1988 ACM Confer- January 1992. ence on LISP and Functional Programming, Snowbird, [44] Mads Tofte. Type abbreviations in signatures. Unpub- Utah, pages 212–223. ACM Press, July 1988. lished manuscript, August 1993. [29] Per Martin-L¨of. Constructive mathematics and com- [45] Diedrik T. van Daalen. The Language Theory of AU- puter programming. In Sixth International Congress for TOMATH. PhD thesis, Technical University of Eind- Logic, Methodology, and Philosophy of Science, pages hoven, Eindhoven, Netherlands, 1980. 153–175. North-Holland, 1982. [46] Niklaus Wirth. Programming in Modula-2. Texts [30] David C. J. Matthews. POLY report. Technical Re- and Monographs in Computer Science. Springer-Verlag, port 28, Computer Laboratory, University of Cam- 1983. bridge, 1982. [31] Robin Milner and Mads Tofte. Commentary on Stan- dard ML. MIT Press, 1991. A The Typing Rules [32] Robin Milner, Mads Tofte, and Robert Harper. The Definition A.1 (Judgements) Definition of Standard ML. MIT Press, 1990. [33] John Mitchell and Robert Harper. The essence of ML.  Γ valid valid context In Fifteenth ACM Symposium on Principles of Pro- Γ  A :: K valid constructor gramming Languages, San Diego, California, January 1988.  Γ  A = A :: K equal constructors [34] John Mitchell, Sigurd Meldal, and Neel Madhav. An Γ  D = D equal declarations extension of Standard ML modules with subtyping and inheritance. In Eighteenth ACM Symposium on Princi- Γ  A ≤ A subtype relation ples of Programming Languages, January 1991. Γ  D ≤ D subfield relation [35] John C. Mitchell and Gordon Plotkin. Abstract types have existential type. ACM Transactions on Program- Γ  M : A well-typed term ming Languages and Systems, 10(3):470–502, 1988. Γ  B : D well-typed binding

[36] Greg Nelson, editor. Systems Programming with Definition A.2 (The field name stripping function) Modula-3. Prentice-Hall, Englewood Cliffs, NJ, 1991. [37] Benjamin Pierce. Bounded quantification is undecid- α K α K able. In Proceedings of the Nineteenth Annual ACM b :: = :: α K A α K A Symposium on Principles of Programming Languages, b :: = = :: = xA x A Albuquerque. ACM, January 1992. y : = : Definition A.3 (Context Formation Rules)  Γ  A2 = A2 :: K •valid (INITIAL-T)   Γ  A1 = A1 :: K⇒K (E-APP)    Γ  A1 A2 = A1 A2 :: K  Γ valid α ∈ dom(Γ) (DEF-O) Γ,α::K  A :: K Γ  A :: K  Γ,α::K valid (E-BETA) Γ  (λα::K.A) A =[A/α]A :: K  Γ,α::K valid Γ  A :: K (DEF-T) Γ,α::K  Aα:: K Γ  A :: K⇒K  Γ,α::K=A valid (E-ETA) Γ  λα::K.Aα = A :: K⇒K Γ  A :: Ω x ∈ dom(Γ) (DEF-V) Γ  V : {b α::K=A}  Γ,x:A valid (ABBREV) Γ  V.b = A :: K Definition A.4 (Constructor Formation Rules)  Γ valid α::K=A ∈ Γ (ABBREV’)  Γ valid α::K ∈ Γ (C-VAR-O) Γ  α = A :: K Γ  α :: K Definition A.6 (Declaration Equality Rules)  Γ valid α::K=A ∈ Γ (C-VAR-T)  Γ,α::K valid Γ  α :: K (EQ-O) Γ  b α::K = b α::K Γ  V : {b α::K} (C-EXT-O) Γ  V.b :: K Γ  A = A :: K  Γ,α::K=A valid (EQ-T) Γ,x:A  A :: Ω Γ  b α::K=A = b α::K=A (C-DFUN)   x A. A  Γ Π : :: Ω Γ  A = A :: Ω  Γ,x:A valid (EQ-V)  Γ valid  xA xA (C-UNIT) Γ y : = y : Γ {}:: Ω Definition A.7 (Subtyping Rules) Γ, D {D1,...,Dn} :: Ω (C-TSUM) {D, D ,...,D } Γ  A = A :: Ω Γ 1 n :: Ω (S-EQ)  A ≤ A Γ,α::K  A :: K Γ (C-LAM)  λα K.A K⇒K Γ :: :: Γ  A ≤ A Γ  A ≤ A (S-TRAN)  Γ  A1 :: K2⇒K Γ  A2 :: K2  A ≤ A (C-APP) Γ Γ  A1 A2 :: K Γ  A2 ≤ A1    Γ,x:A2  A1 ≤ A2 Γ  Πx:A1.A1 :: Ω Definition A.5 (Constructor Equality Rules) (S-DFUN)   Γ  Πx:A1.A1 ≤ Πx:A2.A2 Γ  A :: K (E-REFL)     Γ  A = A :: K Γ  D ≤ D Γ {D ,D1,...,Dm} :: Ω   , D {D1,...,Dn}≤{D ,...,D }  Γ 1 m Γ  A = A :: K    (E-SYM) {D, D1,...,Dn}≤{D ,D ,...,D }  Γ 1 m Γ  A = A :: K (S-TSUM) Γ  A = A :: K Γ  A = A :: K (E-TRAN) Γ {D1,...,Dn,D} :: Ω Γ  A = A :: K (S-THIN) Γ {D1,...,Dn,D}≤{D1,...,Dn} Γ  A1 = A2 :: Ω   Γ,x:A1  A1 = A2 :: Ω Definition A.8 (Subfielding Rules) (E-DFUN)  x A .A x A .A Γ Π : 1 1 =Π : 2 2 :: Ω Γ  D = D  (S-SAME) Γ  D = D Γ  D ≤ D   Γ, D {D1,...,Dn} = {D1,...,Dn} :: Ω     Γ  A ≤ A  Γ,x:A valid Γ {D, D1,...,Dn} = {D ,D1,...,Dn} :: Ω (S-VALUE) (E-TSUM) Γ  y x:A ≤ y x:A

   Γ,α::K=A valid Γ,α::K  A = A :: K (S-FORGET) (E-LAM)  α K A ≤ α K Γ  λα::K.A = λα::K.A :: K⇒K Γ b :: = b :: Definition A.9 (Term Formation Rules) B Undecidability of Subtyping

 Γ valid x:A ∈ Γ The subtyping relation for our system can be shown to (VAR-V) Γ  x : A be undecidable by a slight modification to Benjamin Pierce’s proof of the undecidability of F≤ subtyping [38, 37]. The basic source of undecidability is the sub- Γ,x:A  M : A (LAM)  typing rule (FORGET) that allows the forgetting of Γ  λx:A. M :Πx:A. A information about the type components of translucent sums. Γ  M 1 : A1→A2 Γ  M 2 : A1 (APP) Even a vastly simpler system with transparent and  M M A Γ 1 2 : 2 opaque sums and a forgetting rule is undecidable. In order to demonstrate this as well as simplify the discus-  Γ valid sion, we consider now a very simple fragment of our full ∀i ∈ [1..n]. Γ, D1,...,Di−1  Bi : Di (TSUM) system. Γ {B1,...,Bn} : {D1,...,Dn} λ→,∃,∃= Γ  M : {y x:A} B.1 The fragment (EXT-V) → Γ  M.y : A The fragment λ ,∃,∃= is obtained from our system by restricting the set of constructors to include only types Γ  V : {b α::K,D1,...,Dn} (VALUE-O) and restricting the methods of building types to only Γ  V : {b α::K=V.b,D1,...,Dn} allow for arrow types, binary opaque sums (often called weak sums), and binary transparent sums. We use a  V. A Γ y : slightly different notation to emphasize that these are →,∃,∃= Γ  V : {y x:A, D1,...,Dn} λ (VALUE-V) simpler constructs. The syntax for is as follows:  Γ  V : {y x:A ,D1,...,Dn} Types A ::= α | A1→A2 |∃α.A |∃α=A1.A2 Γ  M : A (COERCE) As before, the meta-variable α ranges over type vari- Γ  M:A : A ables and we identify types that differ only by α- Γ  M : A Γ  A ≤ A conversion. The translation back to our earlier notation (SUBS) is as follows: Γ  M : A α = α Definition A.10 (Binding Formation Rules) A1→A2 =Πx:A1.A2 ∃α.A = {b α::Ω, y x:A} ∃α A .A { α A , xA }  Γ,α::K=A valid = 1 2 = b ::Ω= 1 y : 2 (BIND-T)  α A α K A Γ b = : b :: = The effect of the subtyping rules of our system on this fragment is captured by the following simple set of Γ  M : A  Γ,x:A valid rules: (BIND-V) Γ  y x=M : y x:A → Definition B.1 (Subtyping rules for λ ,∃,∃=)

Lemma A.11 (Properties of the typing system) α ≤ α (VAR)

1. if Γ  A :: K then  Γ valid A ≤ A A ≤ A  A A K  A K  A K 1 1 2 2 (ARROW) 2. if Γ 1 = 2 :: then Γ 1 :: and Γ 2 ::   A1→A2 ≤ A1→A2 3. if Γ  D1 = D2 then  Γ, D1 valid and  Γ, D2 valid A ≤ A (SUM-O) 4. if Γ  A1 ≤ A2 then Γ  A1 :: Ω and Γ  A2 :: Ω ∃α.A ≤∃α.A

5. if Γ  D1 ≤ D2 then  Γ, D1 valid and  Γ, D2 valid [A/α]A1 ≤ [A/α]A2 (SUM-T) 6. if Γ  M : A then Γ  A :: Ω ∃α=A.A1 ≤∃α=A.A2  B D  , D 7. if Γ : then Γ valid [A/α]A1 ≤ [A/α]A2 (FORGET’) 8. if  Γ, D valid then  Γ valid ∃α=A.A1 ≤∃α.A2  αi if ρ = αi    F(ρ)= ∃α, α1,...,αn. ¬(∃α =α, α1=F(ρ1),...,αn=F(ρn). ¬F(ρ1)) if ρ =[α1,...,αn]<ρ1 ...ρn> ∃α, α1,...,αn. ¬α if ρ = HALT

F(R)=∃α=σ, α1=F(ρ1),...,αn=F(ρn). ¬F(ρ1) ≤ σ where R = <ρ1 ...ρn> and    σ = ∃α, α1,...,αn. ¬(∃α =α, α1=α1,...,αn = αn. ¬α)

   Here, α, α , and α1 through αn are fresh variables.

Figure 5: Modifications to Pierce’s encoding of row machines

Note that this set of rules is completely syntax di- subtyping rule could be used here. An example which rected and does not require the use of a context because causes cyclic behavior is then as follows: of the explicit use of substitution. The proof that this P Gα P α ≤ Gα P α set of rules corresponds to the subtyping rules of the ( ( ( ))) ( ( )) = ∃α=Gα(P (α)).¬Gα(P (α)) ≤∃α.¬P (α) original system on this fragment is omitted. For the ⇒ [Gα(P (α))/α](¬Gα(P (α))) ≤ [Gα(P (α))/α](¬P (α)) purposes of the undecidability proof, we will only need = ¬Gα(P (α)) ≤¬P (Gα(P (α))) the following lemma: ⇒ P (Gα(P (α))) ≤ Gα(P (α)) → . Lemma B.2 The subtyping relation for λ ,∃,∃= is re- . flexive. → Theorem B.4 λ ,∃,∃= subtyping is undecidable. The proof proceeds by structural induction on the size of the type using the following measure:16 Pierce’s proof can be found in chapter 6 of his thesis [38] or in [37]. Space considerations prevent outlining |α| =0 it here. The modifications necessary to change his en- |A1→A2| |A1| |A2| → =1+ + coding of row machines so that it produces λ ,∃,∃= |∃α.A| =1+|A| subtyping questions instead are found in Figure 5. The |∃α=A1.A2| =1+|[A1/α]A2| key differences are as follows:

→,∃,∃= B.2 Undecidability of λ subtyping • Use of ∃α=A.A1 ≤∃α.A2 instead of ∀α.A2 ≤ ∀α≤A.A1. Theorem B.3 If the FORGET’ rule is removed, then → λ ,∃,∃= subtyping is decidable. • Use of reflexivity to halt computation instead of the FTOP rule. (Compare the two definitions of Proof: Each use of the other rules strictly decreases the F(HALT)) following non-negative measure, so the simple syntax- directed procedure always terminates in this case: |A1 ≤ A2| = |A1| + |A2|. 2

Note that use of the FORGET’ rule does not decrease this measure and in fact can increase it because the type on the right side can grow without limit in the recursive call. This fact can be used to construct examples that cause the simple syntax-directed procedure for checking →,∃,∃= λ subtyping to loop. For example, consider the following definitions:

¬A = A→α

P (A)=∃α=A.¬A where α fresh Gα(A)=∃α.¬A

The definition of ¬A is chosen so that ¬A1 ≤¬A2 iff A2 ≤ A1. Any type constructor with a contravariant

16 Note that |[A1/α]A2| = |[|A1|/α]A2| if we define |i| = i.