1 Higher-Order and Symbolic Computation, 5, (1999) c 1999 Kluwer Academic Publishers, Boston. Manufactured in The Netherlands. Unchecked Exceptions can be Strictly More Powerful than Call/CC * MARK LILLIBRIDGE ** Systems Research Center Compaq Computer Corporation 130 Lytton Aenue Palo Alto, CA Receied Noember 25, 1995; Reised March 30, 1996 Editor: Oliier Dany Abstract. We demonstrate that in the context of statically-typed purely-functional lambda calculi without recursion, unchecked exceptions (e.g., SML exceptions) can be strictly more powerful than call/cc. More precisely, we proe that a natural extension of the simply-typed lambda calculus with unchecked exceptions is strictly more powerful than all known sound extensions of Girard s F ω (a superset of the simply-typed lambda calculus) with call/cc. This result is established by showing that the first language is Turing complete while the later languages permit only a subset of the recursie functions to be written. We show that our natural extension of the simply-typed lambda calculus with unchecked exceptions is Turing complete by reducing the untyped lambda calculus to it by means of a noel method for simulating recursie types using unchecked-exception returning functions. The result concerning extensions of F ω with call/cc stems from preious work of the author and Robert Harper. Keywords: Studies of programming constructs, control primities, exceptions, recursion, λ- calculus, type theory, functional programming 1. Introduction The relationship between the programming features of exceptions and call/cc (call with current continuation) in statically-typed purely-functional programming languages has been an open question for some time. Carl Gunter and colleagues write in a recent paper : It is folklore (the authors know of no published proof) that neither [unchecked] exceptions nor continuations can be expressed as a macro in terms of the other (at least if no references are present), een though they are closely related. Exceptions in statically-typed programming languages come in two kinds, checked and unchecked. The difference lies in the fact that the type of a function must * This research was sponsored by the Defense Adanced Research Projects Agency, CSTO, under the title The Fox Project: Adanced Deelopment of Systems Software, ARPA Order No. 8313, issued by ESD/AVS under Contract No. F C ** Supported by a National Science Foundation Graduate Fellowship while this work was done.
2 276 MARK LILLIBRIDGE declare only the checked exceptions that it may throw, not the unchecked ones. Most programming languages proide only one kind of exception. For example, all user-declared exceptions in CLU  are checked exceptions 1 while SML  proides only unchecked exceptions. Jaa , from which this terminology comes, is unusual in proiding both kinds. In this paper we demonstrate that under reasonable assumptions unchecked exceptions cannot be expressed as a macro using only call/cc in a statically-typed purely-functional lambda calculi without recursion, thus partially answering half of Gunter et al. s open question. Left open is the question of whether or not unchecked exceptions can be defined using a macro in terms of call/cc and either a fixpoint operator, recursie types, or some similar feature. We do this by showing that when call/cc is added in a sound manner to een as powerful a statically-typed purely-functional lambda calculus as Girard s F ω [10, 22], the set of functions expressible in the resulting language is still a subset of the recursie functions, and that a natural extension with unchecked exceptions of een so limited a language as the simply-typed lambda calculus (λ )isturing complete; that is, it permits all computable functions to be expressed. (In particular, unlike in the first case, potentially non-terminating functions can be written.) This demonstrates that unchecked exceptions are strictly more powerful than call/cc for statically-typed purely-functional lambda calculi without recursion een allowing arbitrary transformations on programs instead of macros cannot reduce unchecked exceptions to call/cc. The first of these results is a preious result of the author with Robert Harper . The second is new to this paper and inoles a noel method for simulating recursie types using unchecked-exception raising functions. Future work on answering Gunter et al. s question will require studying explicitly what can be defined using a macro because the approach taken in this paper of comparing language power (what functions a language can denote) cannot produce negatie results when the base language is already Turing complete, as is the case when recursion is present. Fellesisen s work  proides an excellent foundation for this task. Although it was not Gunter et al. s primary concern, Andrzej Filinski has shown recently that it is possible to define unchecked exceptions in terms of call/cc and references . 2. The Power of Call/CC Like assignment, both call/cc and exceptions can hae non-local effects. Adding non-local effects to a lambda calculus requires specifying an ealuation order in order to retain determinism. Consider, for example, the following untyped code fragment: call/cc (λk. f(k 3, k 4)) If we ealuate arguments left-to-right, then this expression ealuates to 3; ifwe instead ealuate right-to-left, then it ealuates to 4. Each different ealuation order yields a different extension of F ω with call/cc.
3 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 277 The author and Robert Harper considered a number of these extensions in a recent paper  obtaining a number of results, which we summarize briefly here: Four ealuation strategies were considered, differing in whether they use call-by-name or call-by-alue parameter passing and in whether or not they ealuate beneath type abstractions (Λα::K.M). We know of no other proposed ealuation strategies for F ω extended with non-local effects. Not ealuating beneath type abstractions treats type instantiation (M[A]) as a significant computation step, possibility including effects. Strategies of this type are used in Quest  and LEAP , and are directly compatible with extensions that make significant uses of types at run time  (e.g., dynamic types [1, 3]). Since polymorphic expressions are kept distinct from their instances, the anomalies that arise in implicitly polymorphic languages in the presence of references  and control operators  do not arise. Strategies that ealuate beneath type abstractions are inspired by the operational semantics of ML [5, 17]. Ealuation proceeds beneath type abstractions, leading to a once-for-all-instances ealuation of polymorphic terms. Type instantiation is retained as a computation step, but its force is significantly attenuated by the fact that type expressions may contain free type ariables, precluding primities that inductiely analyze their type arguments. The superficial efficiency improement gained by ealuating beneath type abstractions comes at considerable cost since it is incompatible with extensions such as mutable data structures and control operators [25, 12]. The call/cc operator takes one normal argument, which it then calls with the current continuation; if the argument returns, then its alue is the result of the call/cc expression . For example (ignoring types), call/cc (λf.3) yields 3 and call/cc (λf.f 4; 3) yields 4. The obious type for call/cc in F ω was used: 2 call/cc : α:ω. (( u:ω.α u) α) α In English, this means that call/cc[a] M has type A when M is a function that takes an A-accepting continuation and returns a alue of type A, where A-accepting continuations hae type u:ω.a u, reflecting the fact that they do not return. This typing does not distinguish continuations from normal functions. If desired, an abstract type constructor (e.g., α cont) can be used to keep these separate. The only effect of this change is to rule out some programs, so it can only decrease the power of F ω plus call/cc. F ω extended with call/cc was shown to be sound under all the strategies except for the strategy most like ML (the call-by-alue, ealuating beneath type abstractions strategy) which was shown to be unsound for full F ω. Restricting so that polymorphism can only be used on alues, not general expressions, 3 restores soundness for this strategy. This restriction has since been adopted for SML where it is called the alue restriction . Typed CPS (continuation-passing style) transforms were then gien for each strategy from the appropriate sound subset into F ω and proen correct. The proofs of correctness showed that if M terminates with alue V then the transformed ersion of M terminates with a (possibly further reduced) transformed ersion of V. This
4 278 MARK LILLIBRIDGE was done by showing that each reduction step on the original term corresponds to at least one reduction step of the transformed term. Since F ω is known to be strongly normalizing (see ), this means that all programs in the sound subsets must terminate. Hence, adding call/cc to F ω in a sound manner permits only recursie functions to be written; F ω plus call/cc is therefore not Turing complete. It should be noted that because the simply-typed lambda calculus (λ ), the polymorphic lambda calculus (F 2 ), and the core of ML, Core-ML [19, 5], are proper subsets of F ω that this result applies to adding call/cc to them as well. 3. A Language with Unchecked Exceptions Unlike the case with call/cc, we will need to consider only one language with unchecked exceptions. To maximize the strength of our results, we choose to add unchecked exceptions to the weakest typed lambda calculus, the simply-typed lambda calculus (λ ). Because exceptions can hae non-local effects, we must fix an ealuation order before we can extend λ. We choose to use call-by-alue (CBV) ealuation as it seems to be the most natural choice in this setting. (The question of whether or not to ealuate under type abstractions does not arise here because there are no type abstractions in λ.) 3.1. The CBV Simply-Typed Lambda Calculus (λ ) We define the syntax of λ as follows: T ypes A, B ::= unit A 1 A 2 A 1 +A 2 Terms M ::= x () λx:a.m M 1 M 2 left A (M) right A (M) M of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 Assignments Γ ::= Γ,x:A The meta-ariables x and y range oer term ariables. As usual, we identify α- conertible terms and types. We use FV(M) to denote the free term ariables of M and [M/x]M for the usual capture-aoiding substitution of M for x in M. In addition to the usual first-class functions (λx:a.m), we hae included a singleton type unit with sole alue () and disjoint sums (with type A+B). The disjoint sums are not necessary for the primary results of this paper; we hae included them for use in Section 4.1, which proides motiation for the encoding of recursie types using unchecked exceptions. The unit type is included so that we hae at least one base type; any other base type with at least one alue would work as well. The type system of λ consists of a set of rules for deriing judgements of the following forms: Γ Γ M: A well-formed assignment well-formed term The rules for deriing these judgements are standard and can be found in Figure 1.
5 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 279 Γ x dom(γ) Γ,x:A (a-empty) (a-extend) Γ Γ x:γ(x) Γ Γ () : unit Γ,x:A 1 M: A 2 Γ λx:a 1.M : A 1 A 2 Γ M 1 : A 2 A Γ M 2 : A 2 Γ M 1 M 2 : A Γ M: A Γ left A+B (M) :A+B Γ M: B Γ right A+B (M) :A+B Γ M: A 1 +A 2 Γ,x 1 :A 1 M 1 : B Γ,x 2 :A 2 M 2 : B Γ M of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 : B (t-ar) (t-unit) (t-abs) (t-app) (t-left) (t-right) (t-case) Figure 1. Typing rules for λ
6 280 MARK LILLIBRIDGE A context C is an expression of λ with a single hole, written : Contexts C ::=  λx:a. C CM MC left A (C) right A (C) C of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 M of left(x 1 :A 1 )=>C; right(x 2 :A 2 )=>M 2 M of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>C The hole in C may be filled by an expression M, written C[M], by replacing the hole with M, incurring capture of free ariables in M that are bound at the occurrence of the hole. For example, if C = λx:unit., and M = fx, then C[M] =λx:unit.f x. The ariables that are bound within the hole of a context are said to be exposed (to capture) by that context. We write EV (C) for the exposed ariables of a context. Type checking in λ is compositional in the sense that if an expression is welltyped, then so are all its constituent expressions: Lemma 1 (Decomposition) Suppose that λ Γ C[M] :A such that EV (C) dom(γ) =. 4 Then there exists Γ, and B such that: dom(γ )=EV (C) λ Proof: Γ, Γ M: B Routine induction on the structure of contexts. Furthermore, only the type of a constituent of a well-formed expression is releant to typing. Consequently any constituent may be replaced by a term of the same type without affecting typability of the whole expression: Lemma 2 (Replacement) Suppose that λ Γ C[M] :A, with λ Γ, Γ M : B in accordance with the decomposition lemma. If λ Γ, Γ, Γ M : B then λ Γ, Γ C[M ]:A. Proof: Routine induction on typing deriations. Following Plotkin  and Felleisen , we specify an operational semantics by defining the set of alues (V ), the set of ealuation contexts (E), and the one step ealuation relation for that semantics. One-step ealuation is a binary relation on programs that is defined by a set of rules of the form E[R] M, where E is an ealuation context, R is an expression, the redex, and M is determined as a function of E and R. In this case E[R] is said to ealuate to M in one step. We define + to be the irreflexie, transitie closure and to be the reflexie, transitie closure of the relation. A program is a well-typed closed term. We will arrange things so that a program P is either a alue or can be represented in exactly one way as E[R] where E is an ealuation context and R is a redex. Because our ealuation relations will be functions of E and R, this means that our languages will be deterministic. Using this method, the call-by-alue semantics of λ are defined as follows:
7 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 281 V ::= x () λx:a.m left A (V ) right A (V ) E ::=  EM VE left A (E) right A (E) E of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 R ::= (λx:a.m) V left B (V ) of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 right B (V ) of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 E[(λx:A.M) V ] E[[V/x]M] E[left B (V ) of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 ] E[V/x 1 ]M 1 ] E[right B (V ) of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M 2 ] E[V/x 2 ]M 2 ] In the absence of case expressions, these rules specify that the leftmost, outermost term of the form (λx:a.m) V may be reduced in place by replacing it with [V/x]M. Note that the case expression first ealuates its first argument then ealuates exactly one of its branches. Sequential execution (M 1 ; M 2 ) can be obtained by writing (λx:a 1.M 2 )M 1, where A 1 is the type of M 1 and x is not free in M 2. The definition of term ariables (x) as alues is for the benefit of the transformation rules later in this paper. Theorem 1 (Progress) If M is a closed, well-typed expression of type A, then either M is a alue, or else there exist a unique ealuation context E and unique redex R such that M = E[R]. Proof: The proof proceeds by induction on the structure of typing deriations using Lemma 1. Lemma 3 (Substitution) If λ Γ,x:A, Γ M : B and λ Γ M: A then λ Γ, Γ [M/x]M : B. Proof: Routine induction on typing deriations. Theorem 2 (Subject Reduction) If λ λ Γ N: A. Γ M : A and M N, then Proof: By Theorem 1, M = E[R] for some unique ealuation context E and redex R. Hence, by Lemma 1 there exists a type B and assignment Γ such that λ Γ, Γ R: B. By inspecting the definition of the one-step ealuation rules, we see that N = E[N ] and R N for some N. By Lemma 2, we need to show only that λ Γ, Γ N : B. We proceed by cases on the form of R. If R = (λx:a.m ) V, then λ Γ, Γ,x:A M : B, λ Γ, Γ V : A, and N = [V/x]M by inspection; hence, λ Γ, Γ N : B by Lemma 3 as required. The remaining cases are handled similarly. We will be proing ersions of these theorems for many different systems. We will omit their proofs when they are essentially the same as the ones for λ.
8 282 MARK LILLIBRIDGE 3.2. λ extended with unchecked exceptions (λ,e ) We chose to add exceptions to λ by introducing a family of unchecked exceptions parameterized by the type of the alues they carry. For each type A, there is an associated unchecked exception flaor with an operation to raise an exception of that flaor (raise A (M)) and an operation to catch and handle just exceptions of that flaor (M handle x:a => M ). Unlike in SML, it is not possible to hae different flaors of A-carrying exceptions in our system. A more powerful exception system than the one we describe here would hae the ability to dynamically generate new exception flaors at runtime. We do not need this additional power for any of the results in this paper. Indeed, we shall see that with the exception of the simulation of recursie types using unchecked exceptions result in Section 4.2, we will need only one exception flaor to establish our results. This fact means that our primary result about exceptions (λ,e is Turing Complete) can be extended to systems like SML that require exception flaors to be declared before they can be used. Note that because functions are first-class in λ, exceptions may carry functional alues. Our results depend on this ability. While this ability is seldom used in applicatie programming, its analog is used often in object-oriented programming (objects can be thought of as a form of multiple-entry closure). The syntax of λ,e is an extension of that of λ : Terms M ::=... raise A (M) M handle x:a => M No new types are required, but a new type rule is required for each of the new operators: Γ M: A (t-raise) Γ raise A (M) :B Γ M: B Γ,x:A M : B Γ M handle x:a => M : B (t-handle) Note that raise A (M) may be assigned any type since it neer returns normally. The properties of decomposition and replacement remain true: Contexts C ::=... raise A (C) C handle x:a => M M handle x:a => C Lemma 4 (Decomposition) Suppose that λ,e Γ C[M] :A such that EV (C) dom(γ) =. Then there exists Γ and B such that: dom(γ )=EV (C) λ,e Γ, Γ M: B
9 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 283 Lemma 5 (Replacement) Suppose that λ,e Γ C[M] : A, with λ,e Γ, Γ M: B in accordance with the decomposition lemma. If λ,e M : B then λ,e Γ, Γ C[M ]:A. Γ, Γ, Γ As expected, the semantics of λ,e is an extension of that of λ. Because execution of an λ,e program can produce an uncaught exception instead of a alue, it is necessary to generalize our semantic framework so that programs ealuate to outputs (O), a superset of the alues (V ). The definitions for λ,e s semantics follows. F here represents a single frame of an ealuation context that is not a handle expression. We use it to combine all the cases where we propagate a exception up through a non-handle expression into one rule. O ::= V raise A (V ) V ::=... E ::=... raise A (E) E handle x:a => M R ::=... F [raise A (V )] O handle x:a => M F ::=  M V  left A () right A () raise A ()  of left(x 1 :A 1 )=>M 1 ; right(x 2 :A 2 )=>M E[F [raise A (V )]] E[raise A (V )] E[V handle x:a => M] E[V ] E[(raise A (V )) handle x:b => M] E[[V/x]M] (A = B) E[(raise A (V )) handle x:b => M] E[raise A (V )] (A B) Theorem 3 (Progress) If M is a closed, well-typed expression of type A, then either M is an output, or else there exist a unique ealuation context E and unique redex R such that M = E[R]. Theorem 4 (Subject Reduction) If λ,e λ,e Γ N: A. Γ M: A and M N, then 4. The Power of Unchecked Exceptions In this section we proe that λ,e reduction we will use. is Turing complete. We start by motiating the 4.1. Motiation It is standard practice when giing the semantics of untyped programming languages such as Scheme , to explain unchecked exceptions by use of a transform similar in spirit to a CPS transform wherein expressions returning a alue of type A are transformed to expressions that return a alue of type A + σ, where σ is
10 284 MARK LILLIBRIDGE the type of all the alues that may be carried by exceptions. If the original expression ealuates normally to a alue V of type A then the transformed expression ealuates to the alue left A + σ (V ), where V, A, and σ are suitably transformed ersions of V, A, and σ. If, on the other hand, the original expression when ealuated raises an uncaught exception carrying the alue V of type σ then the transformed expression ealuates to right A + σ (V ). The control flow of the original program is then simulated explicitly using case expressions. For example, the translation of raise(m) would first run the transformed code for M then case on the result. If it was a left alue, then we would return it after first switching its tag to right. This corresponds to M returning a alue normally, which is then turned into an exception carrying that alue. If the result was a right alue, we would return it untouched. This corresponds to M raising an exception, which then passes through the raise expression uncaught Exceptions carrying base types Such a transform is easily written in the statically-typed case where there is only one flaor of exception and where σ, the type of alues it carries, is a base type (b). For simplicity, let us consider transforming the subset of λ,e that has no disjoint sums and only has exceptions carrying alues of type σ. Terms from this language, which we call σ-only, may not include left A (M), right A (M), or M of left(x:a) =>M 1 ; right(y:b) =>M 2 as sub-terms and may include raise or handle sub-terms of only the form raise σ (M) or M handle x:σ => M. σ-only is closed under λ,e ealuation: Lemma 6 (Closure) If M is a σ-only term and M N under λ,e a σ-only term. then N is Proof: Inspection of the one-step ealuation relation for λ,e shows that it maps σ-only terms to σ-only terms. A transform of this kind from σ-only to λ for the case when σ is a base type can be found in Figure 2. Unless we say otherwise, σ will be assumed to be a base type throughout the rest of this section (Section 4.1.1). The main transform is computed by the judgement Γ M: A M, which says that the σ-only computation M of type A transforms to the λ -term M, which will hae type [A] under applied pointwise to Γ ( Γ ). A sub-judgement, Γ V : A V, is used to transform σ-only alues into λ alues with type A under Γ. A number of macros used by the transform can be found in Figure 3. Note that the transformation of a alue differs from the transformation of the computation that immediately returns that alue because only the later will be wrapped in a left tag. The B-APP-V and B-RAISE-V rules are specialized ersions of the B-APP and B-RAISE rules that produce more optimized code for the case when M 1 or M is a alue. This optimization is needed to ensure that one λ,e ealuation step on a σ-only term is simulated by one or more λ ealuation steps on the transformed ersion of the term (see Theorem 5 below). Without this simulation result, it is much harder to proe the correctness of the transforms.
11 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 285 b = b A 1 +A 2 = A 1 + A 2 A 1 A 2 = A 1 [A 2 ] [A] = A + σ Γ Γ x:γ(x) x Γ Γ () : unit () Γ,x:A 1 M: A 2 M Γ λx:a 1.M : A 1 A 2 λx: A 1.M (b-ar) (b-unit) (b-abs) Γ V : A V Γ V : A left [A] (V ) Γ V : A 2 A V Γ M: A 2 M Γ VM: A apply(v,m,a 2,A) (b-alue) (b-app-) M 1 not a λ,e -alue Γ M 1 : A 2 A M 1 Γ M 2 : A 2 M 2 Γ M 1 M 2 : A apply(m 1,M 2,A 2,A) Γ V : σ V Γ raise σ (V ):A raise(a, V ) M not a λ,e -alue Γ M: σ M Γ raise σ (M) :A raise(a, M ) Γ M: A M Γ,x:σ N: A N Γ M handle x:σ => N: A handle(x, A, M,N ) (b-app) (b-raise-) (b-raise) (b-handle) Figure 2. Exception transform for σ a base type
12 286 MARK LILLIBRIDGE apply(m 1,M 2,A 2,A) = M 1 of (x FV(M 2 )) left(x: A 2 A ) => apply(x, M 2,A 2,A); right(x: σ ) => right [A] (x) apply(v,m,a 2,A) = M of (x FV(V )) left(x: A 2 )=>Vx right(x: σ ) => right [A] (x) raise(a, M) = M of left(x: σ ) => raise(a, x) right(x: σ ) => right [A] (x) raise(a, V ) = right [A] (V ) handle(x, A, M, N) = M of left(x: A ) => left [A] (x); right(x: σ ) =>N Figure 3. Macros used by the transform
13 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 287 The transforms are defined on all well-typed σ-only alues and terms when σ is a base type: Lemma 7 (Completeness) Let V and M be σ-only alues and terms respectiely. 1. If λ,e Γ V : A then a λ -alue V such that Γ V : A V. 2. If λ,e Γ M: A then a λ -term M such that Γ M: A M. Proof: Routine simultaneous induction on the deriations of λ,e and λ,e Γ M: A. Γ V : A (For certain Γs, Ms, and As, the transform can yield seeral different M s that differ only in the types they contain because the ariable A in the B-RAISE rule is unconstrained due to the polymorphism of the raise σ ( ) operator.) Moreoer, they result in well-typed λ terms and alues with the appropriate types: Lemma 8 (Preseration) Let V and M be drawn from σ-only while V and M are drawn from λ. 1. If Γ V : A V then λ,e Γ V : A and λ Γ V : A. 2. If Γ M: A M then λ,e Γ M: A and λ Γ M :[A]. Proof: Proed by simultaneous induction on the deriations of Γ V : A V and Γ M: A M. They also distribute oer substitution: Lemma 9 (Substitution) Suppose Γ V : A V. Then: 1. If Γ,x:A, Γ V 2 : B V 2 then Γ, Γ [V/x]V 2 : B [V /x]v If Γ,x:A, Γ M: B M then Γ, Γ [V/x]M : B [V /x]m. Proof: Proed by routine simultaneous induction on the deriations of Γ,x:A, Γ V 2 : B V 2 and Γ,x:A, Γ M: B M, using the fact that N is a alue iff [V/x]N is a alue. Proing the transforms correct is done through showing that each ealuation step in λ,e on an original σ-only term is simulated in λ on the transformed term by at least one step: Theorem 5 (Simulation) Suppose M is a σ-only term, Γ M: A M and M N under λ,e. Then there exists N such that Γ N: A N and M + N under λ. Proof: Proed by induction on M. Sample cases:
14 288 MARK LILLIBRIDGE LAM: Here M = λx:a 1.M 1. This case is impossible because inspection of λ,e s one-step ealuation relation shows that it neer applies to lambdas. APP1M: Here M = M 1 M 2, where M 1 is not a λ,e output. By B-APP, A 2,M 1,M 2 such that Γ M 1 : A 2 A M 1,Γ M 2 : A 2 M 2, and M = apply(m 1,M 2,A 2,A). Inspection of the semantic definitions for λ,e shows that it must be the case that there exists N 1 such that N = N 1 M 2 and M 1 N 1 under λ,e. By the induction hypothesis, N 1 such that Γ N 1 : A 2 A N 1 and M 1 + N 1 under λ M = apply(m 1,M 2,A 2,A) + apply(n 1,M 2,A 2,A) under λ. Two cases need to be considered: N 1 is a λ,e alue: By B-VALUE, V 1 such that Γ V 1 : A 2 A V 1 and N 1 = left [A2 A] (V 1). It is easy to erify that apply(n 1,M 2,A 2,A) = apply(left [A2 A] (V 1),M 2,A 2,A) apply(v 1,M 2,A 2,A) M + apply(v 1,M 2,A 2,A) (all under λ ). By B-APP-V, Γ N: A apply(v 1,M 2,A 2,A). otherwise: By B-APP, Γ N: A apply(n 1,M 2,A 2,A). HANR: Here M =(raise σ (V 1 )) handle x:σ => M 2 [V 1 /x]m 2 under λ,e.by B-HANDLE and B-RAISE-V, V 1,M 2 such that Γ V 1 : σ V 1, Γ,x:σ M 2 : A M 2, and M = handle(x, A, right [A] (V 1),M 2) [V 1/x]M 2 under λ. Hence by Lemma 9, Γ [V 1 /x]m 2 : A [V 1/x]M 2. To see where this result goes wrong if we do not use the specialized ersions of apply and raise, consider the case where M = VM 1, N = VM 2, and M 1 M 2 under λ,e. To get our desired simulation result, we will need to show that M = apply(left [A2 A] (V ),M 1,A 2,A) + apply(left [A2 A] (V ),M 2,A 2,A)= N under λ for appropriate A 2 and A. It is easy to erify that apply(left [A2 A] (V ),M 1,A 2,A) + apply(v,m 1,A 2,A) + apply(v,m 2,A 2,A) under λ (the second part by induction). Howeer, it is not the case that apply(v,m 2,A 2,A) apply(left [A2 A] (V ),M 2,A 2,A) under λ so the result fails. (The later is an expansion of the former.) Lemma 10 (Stopping) If Γ M: A M then M is a λ,e output iff M is a λ alue. Proof: Proed by inspection of the definitions of the transform and the semantics of λ and λ,e. Theorem 6 (Correctness) Suppose P is a σ-only program of type A. there exists P such that P : A P and Then
15 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC The ealuation of P under λ,e terminates. terminates iff the ealuation of P under λ 2. If P O under λ,e then O such that O: A O and P O under λ. 3. If P V under λ, then exists a σ-only output O such that O: A V and P O under λ,e. Proof: P exists by Lemma 7. Consider the (possibly infinite) chain of terms resulting from applying the one-step ealuation function of λ,e repeatedly to P (=P 0 ): P 1, P 2,... By repeatedly applying Theorem 5, we can generate a corresponding chain of λ terms P 0 (= P ), P 1, P 2,... such that P i : A P i and i. P i + P i+1 under λ. By Lemma 10, the chains must either both be infinite in length, or both be of the same length (say n) with P n a λ,e output and P n a λ alue. By Lemma 6, i. P i is a σ-only term. The desired results follow. Problems arise if we try and use this transform when σ is a non-base type. In particular, if σ is an arrow type, infinite recursion results at the type leel, preenting the transform from working because infinite types are not permitted in λ. (For example, if σ = int int then σ = int [int] =int ( int + σ ) = int (int+(int ( int + σ ))) =...) This suggests that if we add recursie types to the destination calculus, we can make the transform work on arrow types. We will consider such a transform in Section after we introduce a suitable target calculus λ extended with recursie types (λ,µ ) We can obtain such a calculus by adding recursie types (µα.a) toλ. We use a formulation of recursie types where there is an isomorphism µα.a = [µα.a/α]a mediated by two built in primities, unroll µα.a ( ) in the forward direction and roll µα.a ( ) in the backward direction, such that unroll µα.a (roll µα.a (V )) V. The syntax of λ,µ is an extension of that of λ : T ypes Terms Assignments A, B ::=... α µα.a M ::=... roll A (M) unroll A (M) Γ ::=... Γ,α The meta-ariable α ranges oer type ariables. We use FTV (A) to denote the free type ariables of A and [A/α]A for the usual capture-aoiding substitution of A for α in A. The type system of λ,µ extends that of λ. Because types may now contain type ariables, an additional judgement is needed to check that types do not contain type ariables unbound by the current assignment:
16 290 MARK LILLIBRIDGE Γ α dom(γ) Γ,α (a-type) Γ A x dom(γ) Γ,x:A (a-extend2) Γ α dom(γ) Γ α Γ Γ unit (k-ar) (k-unit) Γ A Γ B Γ A B Γ A Γ B Γ A+B Γ,α A Γ µα.a (k-arrow) (k-dsum) (k-rec) Γ M: A Γ B Γ left A+B (M) :A+B Γ M: B Γ A Γ right A+B (M) :A+B Γ M:[µα.A/α]A Γ µα.a Γ roll µα.a (M) :µα.a Γ M: µα.a Γ unroll µα.a (M) :[µα.a/α]a (t-left2) (t-right2) (t-roll) (t-unroll) Figure 4. New type rules for λ,µ
17 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 291 Γ A well-formed type The rules for implementing this new judgement as well as for typing roll A (M) and unroll A (M) appear in Figure 4. Rules A-EXTEND2, T-LEFT2, and T-RIGHT2 replace the corresponding rules of λ ; they are needed to ensure that if Γ M: A then Γ A. The properties of decomposition and replacement remain true: Contexts C ::=... roll A (C) unroll A (C) Lemma 11 (Decomposition) Suppose that λ,µ Γ C[M] : A such that EV (C) dom(γ) =. Then there exists Γ and B such that: dom(γ )=EV (C) λ,µ Γ, Γ M: B Lemma 12 (Replacement) Suppose that λ,µ Γ C[M] :A, with λ,µ Γ, Γ, Γ Γ, Γ M: B in accordance with the decomposition lemma. If λ,µ M : B then λ,µ Γ, Γ C[M ]:A. The semantics of λ,µ is an extension of that of λ : V ::=... roll A (V ) E ::=... roll A (E) unroll A (E) R ::=... unroll A (roll A (V )) E[unroll A (roll A (V ))] E[V ] Theorem 7 (Progress) If M is a closed, well-typed expression of type A, then either M is a alue, or else there exist a unique ealuation context E and unique redex R such that M = E[R]. Theorem 8 (Subject Reduction) If λ,µ λ,µ Γ N: A. Γ M: A and M N, then Exceptions carrying functional types By retargeting our transform from λ to λ,µ and altering its definition slightly, we can make it work een when σ is an arrow type. Figure 5 contains the necessary modifications to our transform: the new transform is composed of the definitions of this figure plus those of Figures 2 and 3, except that where there are two definitions for the same name, only the new definition is used. The most important change here is to the definitions of what types transformed alues ( ) and computations ([ ]) hae. Instead of transformed exceptional alues (the arguments of right A ( )) being of type σ, they now are of type
18 292 MARK LILLIBRIDGE b α = b A 1 +A 2 α = A 1 α + A 2 α A 1 A 2 α = A 1 α [A 2 ] α [A] α = A α + α γ = µα. σ α A = A γ [A] = [A] γ (= A + γ) apply(m 1,M 2,A 2,A) = M 1 of (x FV(M 2 )) left(x: A 2 A ) => apply(x, M 2,A 2,A); right(x:γ) => right [A] (x) apply(v,m,a 2,A) = M of (x FV(V )) left(x: A 2 )=>Vx right(x:γ) => right [A] (x) raise(a, M) = M of left(x: σ ) => raise(a, x) right(x:γ) => right [A] (x) raise(a, V ) = right [A] (roll γ (V )) handle(x, A, M, N) = M of left(x: A ) => left [A] (x); right(x:γ) => (λx: σ.n) unroll γ (x) Figure 5. Exception transform using recursie types
19 UNCHECKED EXCEPTIONS CAN BE STRICTLY MORE POWERFUL THAN CALL/CC 293 γ = µα. σ α, where α is the old definition of modified to use α as the type of transformed exception alues. These definitions ensure that A and [A] are always well defined. Unlike before, though, explicit roll and unroll operations need to be inserted to conert between γ and σ = σ γ ; these show up in the raise and handle functions. The only other change required is to the type argument of the right(x : ) pattern matcher in the case statements (from σ to γ). Although σ is now free to be any λ,e type, the transforms are still defined on only well-typed σ-only alues and terms: Lemma 13 (Completeness) Let V and M be σ-only alues and terms respectiely. 1. If λ,e 2. If λ,e Γ V : A then a λ,µ -alue V such that Γ V : A V. Γ M: A then a λ,µ -term M such that Γ M: A M. Proof: Routine simultaneous induction on the deriations of λ,e and λ,e Γ M: A. Γ V : A All of the results preiously proed for the original transform carry oer to the new transform; we omit proofs that are essentially the same as the preious ersions: Lemma 14 (Preseration) Let V and M be drawn from σ-only while V and M are drawn from λ,µ. 1. If Γ V : A V then λ,e 2. If Γ M: A M then λ,e Γ V : A and λ,µ Γ M: A and λ,µ Γ V : A. Γ M :[A]. Lemma 15 (Substitution) Suppose Γ V : A V. Then: 1. If Γ,x:A, Γ V 2 : B V 2 then Γ, Γ [V/x]V 2 : B [V /x]v If Γ,x:A, Γ M: B M then Γ, Γ [V/x]M : B [V /x]m. Theorem 9 (Simulation) Suppose M is a σ-only term, Γ M: A M and M N under λ,e. Then there exists N such that Γ N: A N and M + N under λ,µ. Proof: Proed by induction on M. Most cases are ery similar to the preious theorem, with one exception: HANR: Here M = (raise σ (V 1 )) handle x:σ => M 2 [V 1 /x]m 2 under λ,e with x FV(V 1). By B-HANDLE and B-RAISE-V, V 1,M 2 such that Γ V 1 : σ V 1, Γ,x:σ M 2 : A M 2, and M = handle(x, A, right [A] (roll γ (V 1)),M 2) [roll γ (V 1)/x]((λx: σ.m 2) unroll γ (x)) =(λx: σ.m 2) unroll γ (roll γ (V 1)) (λx: σ.m 2) V 1 [V 1/x]M 2 under λ,µ. Hence by Lemma 15, Γ [V 1 /x]m 2 : A [V 1/x]M 2.
20 294 MARK LILLIBRIDGE Lemma 16 (Stopping) If Γ M: A M then M is a λ,e a λ,µ alue. output iff M is Theorem 10 (Correctness) Suppose P is a σ-only program of type A. Then there exists P such that P : A P and 1. The ealuation of P under λ,e terminates. λ,µ terminates iff the ealuation of P under 2. If P O under λ,e then O such that O: A O and P O under λ,µ. 3. If P V under λ,µ, then exists a σ-only output O such that O: A V and P O under λ,e. A question naturally arises: since, as we hae seen, the transform suggests that unchecked exceptions carrying arrow types hae an inherently recursie character, can we simulate recursie types using unchecked exceptions capable of carrying arrow types? The following section answers this question in the affirmatie Simulating recursie types with exceptions Suppose we wish to encode the λ,µ alues of a recursie type µα.a using the λ,e alues of some type µα.a. What properties do we need of µα.a? Most importantly, we need the following isomorphism so we can implement roll and unroll on our encoded terms: 5 µα.a = [µα.a/α]a Ideally, we would like our transform to be compositional so that [A/α]B =[A/α]B; this means that the desired isomorphism is really between µα.a and [µα.a/α]a. Because recursie types hae no non-local effects, we should be able to make only local changes to recursie alues and types. This means that should distribute oer type constructors other than µ (e.g., A+B = A+B) and that b should equal b. Accordingly, we should hae that A = A when A contains no recursie types. Thus, if we consider the simple case where A contains no recursie types, the isomorphism means that we hae to be able to pack a alue of type [µα.a/α]a into a alue of type µα.a. We cannot do this in λ because, in general, alues of the former type will contain much more information than alues of the later type. If we are to succeed, we need a way to smuggle more information out of some alues than their type suggests they can proide. Functions that can raise unchecked exceptions proide this ability. Consider a function of the simplest functional type unit unit that can raise an exception carrying alues of type σ: if we apply the transform of the last section, we see that it can be modeled by a λ,µ alue of