A Functional Abstraction of Typed Invocation Contexts

In their paper"A Functional Abstraction of Typed Contexts", Danvy and Filinski show how to derive a monomorphic type system of the shift and reset operators from a CPS semantics. In this paper, we show how this method scales to Felleisen's control and prompt operators. Compared to shift and reset, control and prompt exhibit a more dynamic behavior, in that they can manipulate a trail of contexts surrounding the invocation of previously captured continuations. Our key observation is that, by adopting a functional representation of trails in the CPS semantics, we can derive a type system that encodes all and only constraints imposed by the CPS semantics.


Introduction
Delimited continuations have been proven useful in diverse domains.Their applications range from representation of monadic effects [Fil94], to formalization of partial evaluation [Dan96], and to implementation of automatic differentiation [WZD + 19].As a means to handle delimited continuations, researchers have designed a variety of control operators [Fel88, DF90, GRR95, DPJS07, MB11].Among them, Danvy and Filinski's [DF90] shift/reset operators have a solid theoretical foundation: there exist a simple CPS translation to the pure λ-calculus [DF90], an expressive type system that allows modification of answer types [DF89], and a set of equational axioms that are sound and complete with respect to the CPS translation [KH03].A variation of shift/reset, known as shift0/reset0, also have similar theoretical artifacts, due to recent work by Materzok and Biernacki [MB11,Mat13].Other variants, however, are not as well-understood as the aforementioned ones, because there is currently no simple CPS semantics for those variants.
Understanding the subtleties of control operators is important, especially given the rapid adoption of algebraic effects and handlers [PP09,BP15] observed in the past decade.
Effect handlers can be thought of as a generalization of exception handlers that provide access to the continuation surrounding an exception.It is known that effect handlers have a close connection with control operators [FKLP17,PPS19], and they are often implemented using control operators provided by the host language [KLO13,KS16].This means a wellestablished theory of control operators is crucial for safer and more efficient implementation of effect handlers.
In this paper, we formalize a typed calculus of control and prompt, a pair of control operators proposed by Felleisen [Fel88].These operators bring an interesting behavior into programs: when a captured continuation k is invoked, the subsequent computation may capture the context surrounding the invocation of k.From a practical point of view, the ability to manipulate invocation contexts is useful for implementing sophisticated algorithms, such as list reversing [BDM06] and breadth-first traversal [BDS06].From a theoretical perspective, on the other hand, this ability makes it hard to type programs in a way that fully reflects their runtime behavior.
We address the challenge with typing by rigorously following Danvy and Fillinski's [DF89] recipe for building a type system of a delimited control calculus.The idea is to analyze the denotational semantics of the calculus -essentially a CPS translation -and identify all the constraints that are necessary for making the denotation well-typed.In fact, the recipe has been applied to the control and prompt operators before [KY08], but the type system obtained is not satisfactory for two reasons.First, the type system imposes certain restrictions on the contexts in which a captured continuation may be invoked.Second, the type system does not precisely describe the way contexts compose and propagate during evaluation.We show that, by choosing a right representation of invocation contexts in the CPS translation, we can build a type system without such limitations.
Below is a summary of our specific contributions: • We present a type system of control and prompt that accounts for manipulation of invocation contexts.The type system is the control/prompt-equivalent of Danvy and Filinski's [DF89] type system for shift/reset, in that it incorporates all and only constraints that are imposed by the monomorphically typed CPS translation.• We prove two properties of our type system: type soundness and type preservation of the CPS translation.We also provide a partial proof of termination, which does not hold for the existing type system of control and prompt [KY08].• We further design a more fine-grained type system that distinguishes between pure and impure expressions, and define a selective CPS translation based on the type system.The selective translation is crucial for practical implementation of control and prompt, as it generates less administrative redexes.• We formalize our calculi and CPS translations in the Agda proof assistant [Nor07].The formalization serves as the mechanized proofs of the theorems stated in the paper (except the progress theorem), and is available online at: https://github.com/YouyouCong/lmcs-artifact We begin with an informal account of control and prompt (Section 2), highlighting the dynamic behavior of these operators.We next formalize an untyped calculus of control/prompt (Section 3) and its CPS translation (Section 4).Then, from the CPS translation, we derive a type system of our calculus (Section 5), and prove its properties (Section 6).Having established a basic typing principle, we refine the calculus with the notion of purity, and define a selective CPS translation (Section 7).After that, we briefly explain how we developed our Agda formalization.Lastly, we discuss related work (Section 9) and conclude with future directions (Section 10).
Relation to Prior Work.This is an updated and extended version of our previous paper [CIHA21].The primary new contribution of this version is the fine-grained calculus and selective CPS translation developed in Section 7. We also used the extra space to describe our Agda formalization and expand various discussions.

Control and Prompt
In this section, we familiarize the reader with control and prompt by walking through two examples.These examples exhibit the dynamic behavior of control and prompt, as well as the heterogeneous nature of captured contexts.
2.1.The Dynamic Behavior of Control.The control and prompt operators are control primitives for capturing and delimiting continuations.To see how these operators behave, let us look at the following program: Throughout the paper, we write F to mean control and to mean prompt.Under the call-by-value, left-to-right evaluation strategy, the above program evaluates in the following way: The first control operator captures the delimited context up to the enclosing prompt, namely From this example, we observe that a control operator can capture the context surrounding the invocation of a previously captured continuation.More generally, control may capture a trail of such invocation contexts.The ability comes from the absence of the delimiter in the body of captured continuations.Indeed, if we replace control with shift (S) in the above program, the second shift would have no access to the context 2 * [.], since the first shift would insert a reset into the continuation k 1 .As a consequence, the program yields a different result 45.
In the continuations literature, control/prompt are classified as dynamic, because they require us to actually run a program in order to see what continuation a control captures.In contrast, shift/reset are called static, as they allow us to determine the extent of continuations from the lexical information of a program.

2.2.
The Heterogeneous Nature of Trails.In the example discussed above, we only had contexts whose input and output types are both int.In practice, however, we may wish to deal with contexts having different input and output types.Here is such an example: We assume two primitive functions: is0, which tells us if a given integer is zero or not, and b2s, which converts a boolean into a string "true" or "false".Below is the reduction sequence of the above program: The first control operator captures the delimited context [.] + (Fk 2 .b2s (k 2 8)), and invokes it in the context is0 [.].The second control captures the context is0 (5 + [.]), and invokes it in the context b2s [.].By composing these contexts, and by plugging 8 into the hole, we obtain b2s (is0 (5 + 8)), which evaluates to the string "false".
From this example, we observe that a trail of invocation contexts can be heterogeneous.In particular, the input and output types of each context can be different.Of course, the invocation contexts in a heterogeneous trail must align in a way that makes their composition Evaluation Contexts Figure 1: Syntax and Reduction of λ F type-safe.The type safety holds when the input type of an invocation context is equal to the output type of the previous context.It is easy to see that example (2) meets this condition: the original delimited context (5 + [.]) is int-to-int, the first invocation context (is0 [.]) is int-to-bool, and the second invocation context (b2s [.]) is bool-to-string.Therefore, the application b2s (k 2 8) is well-typed.It turns out that example (2) is judged ill-typed by the existing type system for control and prompt [KY08].This is because the type system imposes the following restrictions on the type of invocation contexts.
• All invocation contexts within a prompt clause must have the same type.
• For each invocation context, the input and output types must be the same.
We claim that, a fully expressive type system of control and prompt should be more flexible about the type of invocation contexts.Now the question is: Is it possible to allow such flexibility?Our answer is "yes".As we will see in Section 5, we can build a type system that accommodates invocation contexts having different types, and that accepts example (2) as a well-typed program.

λ F : A Calculus of Control and Prompt
Having seen how control and prompt behave, we define a formal calculus of these operators.
In Figure 1, we present λ F , a (currently untyped) λ-calculus extended with control and prompt.The calculus has a separate syntactic category for values, which includes integers, variables, and abstractions.Expressions consist of values, application, and delimited control constructs control and prompt.
We equip λ F with a call-by-value, left-to-right evaluation strategy.As is usual with delimited control calculi, there are two groups of evaluation contexts: general contexts (E) and pure contexts (F ).Their difference is that general contexts may contain prompt surrounding a hole, while pure contexts can never have such prompt.The distinction is used in the reduction rule (F) of control, which says, control always captures the context Evaluation Contexts Reduction Rules Figure 2: Syntax and Reduction of λ C up to the nearest enclosing prompt.In the reduct, we see that the body of a captured continuation is not surrounded by prompt, as we observed in the previous section.On the other hand, the body of control is evaluated in a prompt clause.The reduction rule (P) for prompt simply removes a delimiter surrounding a value.

CPS Translation
In the previous section, we defined the semantics of control and prompt directly on λ F expressions.Another way to define the semantics is to convert λ F expressions into the plain λ-calculus, via a continuation-passing style (CPS) [DF89] translation.In this section, we give a CPS translation of control and prompt.
When the source calculus has control and prompt, a CPS translation exposes continuations and trails of invocation contexts.Among these, trails can be represented either as a list of functions [BDM06,BDM15] or as a composition of functions [Sha07].Previous work [KY08] on typing control and prompt adopts the list representation, because it is conceptually simpler.We, however, adopt the functional representation, as it makes it easier to build a fully expressive type system (see Section 5).4.1.λ C : Target Calculus of CPS Translation.In Figure 2, we define the target calculus of the CPS translation, which we call λ C .The calculus is a pure, call-by-value λ-calculus featuring the unit value (), which represents an empty trail, and a case analysis construct, which allows inspection of trails.Note that a non-empty trail is represented as a regular function.Note also that we use v and t as both meta-level and object-level variables denoting values and trails.
As in λ F , we evaluate λ C programs under a call-by-value, left-to-right strategy.The choice of evaluation strategy in the target calculus is not important in our setting, but it matters if the target calculus has computational effects (such as non-termination and I/O), because the CPS image of control and prompt has non-tail calls.34:7 n = λk.λt.k n t x = λk.λt.k x t λx. e = λk.λt.k (λx.λk 1 .λt 1 .e k 1 t 1 ) t e 1 e 2 = λk.λt. e 1 (λv 1 .λt 1 .e 2 (λv 2 .λt 2 .v 1 v 2 k t 2 ) t 1 ) t Fc. e = λk.λt. e [λx.λk 1 .λt 1 .k x (t @ (k 1 :: t 1 ))/c] k id () Figure 3: CPS Translation of λ F Expressions 4.2.The CPS Translation.In Figure 3, we present the CPS translation from λ F to λ C , which is equivalent to the translation given by Shan [Sha07].The translation converts an expression into a function that takes in a continuation k and a trail t.The continuation receives a value and a trail and produces an answer.The trail is the composition of the invocation contexts encountered so far.Here is an informal typing of continuations and trails: The formal typing is obtained by specifying the type of each component (see Section 5.1).
Below, we detail the translation of three representative constructs: variables, prompt, and control.
Variables.The translation of a variable is an η-expanded version of the standard, call-byvalue translation.The trivial use of the current trail t communicates the fact that a variable can never change the trail during evaluation.More generally, the CPS translation of a pure expression uniformly calls the continuation with an unmodified trail.
Prompt.The translation of prompt has the same structure as the translation of variables, because prompt forms a pure expression.The translated body e is run with the identity continuation k id and an empty trail () 1 , describing how prompt resets the context of evaluation.Note that, in this CPS translation, the identity continuation is not the identity function.It receives a value v and a trail t, and behaves differently depending on whether t is empty or not.When t is empty, the identity continuation simply returns v.When t is non-empty, t must be a function composed of one or more invocation contexts, which looks like λx.E n [... E 1 [x] ...].In this case, the identity continuation builds an expression

.] by calling the trail with v and ().
Control.The translation of control shares the same pattern with the translation of prompt, because its body is evaluated in a prompt clause (as defined by the (F) rule in Figure 1).The translated body e is applied a substitution that replaces the variable c with the trail t @ (k 1 :: t 1 ), describing how an invocation of a captured continuation extends the trail 2 .The extension is necessary for correctly computing the continuations captured during the invocation of c.In particular, it makes the invocation context k 1 of c accessible to the control operators that are executed during the invocation of c. Recall that, in this CPS translation, trails are represented as functions.The @ and :: operators are thus defined as a function producing a function 3 .More specifically, these operators compose contexts in a first-captured, first-called manner (as we can see from the second clause of ::).Notice that :: is defined as a recursive function 4 .The reason is that, when extending a trail t with a continuation k, we need to produce a function that takes in a trail t 1 , which in turn must be composed with a continuation k 1 .
The CPS translation is correct with respect to the definitional abstract machine given by Biernacka et al. [BBD05].The statement is proved by Shan [Sha07], using the functional correspondence [ABDM03] between evaluators and abstract machines.We are also developing a mechanized proof of correctness in Agda.The goal is to show that, if two λ F expressions are related by reduction, their CPS images are related by observational equivalence.We have proved all cases but the control reduction (rule (F) in Figure 1), which requires careful reasoning on the equivalence of trails.
As a last note, let us mention here that the alternative CPS translation of control and prompt, where trails are represented as lists, can be obtained by replacing () with the empty list, and the two operations @ and :: with ones that work on lists.

Type System
The CPS translation defined in the previous section shows how control and prompt manipulate continuations and trails.Guided by this behavior, we now derive a type system of λ F .We proceed in three steps.First, we specify the syntax of trail types (Section 5.1).Next, we identify an appropriate form of typing judgment (Section 5.2).Lastly, we define the typing rules of individual syntactic constructs (Section 5.3).In each step, we contrast our outcome with its counterpart in Kameyama and Yonezawa's [KY08] type system, showing how different representations of trails in the CPS translation lead to different typing principles.5.1.Syntax of Trail Types.Recall from Section 4.1 that, in λ C , trails have two possible forms: () or a function.Correspondingly, in λ F , trail types µ are defined by a two-clause grammar: • | τ → µ τ .The latter type is interpreted in the following way.
• The trail accepts a value of type τ .
2 There is a superficial difference between our CPS translation and Shan's original translation [Sha07].In our translation rule for control, the continuation variable c is replaced by the function λx.λk1.λt1.k x (t @ (k1 :: t1)).In Shan's translation, c is replaced by λx.λk1.λt1.(k :: t) x (k1 :: t1).However, by expanding the definition of @ and ::, we can easily see that the two functions are equivalent.We prefer the one that uses @ because it is closer to the abstract machine given by Biernacki et al. [BDM15], as well as the list-based CPS translation derived from it.
3 The :: function is equivalent to Shan's compose function. 4While recursive, the :: function is guaranteed to terminate, as the types of the two arguments become smaller in every three successive recursive calls (or they reach the base case in fewer steps).
• The trail is to be composed with a context of type µ.
• After the composition, the trail produces a value of type τ .Put differently, τ is the input type of the innermost invocation context, τ is the output type of the context to be composed in the future, and µ is the type of this future context.
To get some intuition about trail typing, let us revisit example (2) from Section 2.2.
When evaluation goes inside of prompt, the trail is initialized to an empty one ().Such a trail is naturally given type •.
When the continuation k 1 is invoked, the trail is extended with the context is0 [.].This context will be composed with the invocation context b2s [.] of k 2 later in the reduction sequence.Therefore, the trail at this point is given type int → bool → • string string, consisting of the input type of is0, the type of b2s, and the output type of b2s.
When the continuation k 2 is invoked, the trail is extended with the context b2s [.] (hence the whole trail looks like b2s (is0 [.])).This context will not be composed with any further contexts in the subsequent steps of reduction.Therefore, the trail at this point is given type int → • string, consisting of the input type of is0, the type of an empty trail, and the output type of b2s.
Observe that our trail types can be inhabited by heterogeneous trails (e.g., b2s (is0 [.])), where the input and output types of each invocation context are different.The flexibility is exactly what we expect an expressive type system of control and prompt to have, as we stated in Section 2.2.
Comparison with Previous Work.In the CPS translation of Kameyama and Yonezawa [KY08], a trail is treated as a list of invocation contexts.Such a list is given a recursive type Trail(ρ) defined as follows: We can easily see that the definition restricts the type of invocation contexts in two ways.First, all invocation contexts in a trail must have the same type.This is because lists are homogeneous by definition.Second, each invocation context must have equal input and output types.This is a direct consequence of the first restriction.The two restrictions prevent one from invoking a continuation in a context such as is0 [.] or b2s [.].Moreover, the use of the list type makes empty and non-empty trails indistinguishable at the level of types, and extension of trails undetectable in types.On the other hand, the limited expressiveness allows one to use an ordinary expression type (such as int, instead of a type designed specifically for trails) to encode the information of trails in the control/prompt calculus.That is, if a trail has type Trail(ρ) in the CPS world, it has type ρ in the direct-style world.5.2.Typing Judgment.Recall from Section 4.2 that a λ F expression e is CPS-translated into a function λk.λt. e .Assuming e has type τ , the translated function can be typed in the following way: Here, α and β are answer types, representing the return type of the enclosing prompt before and after evaluation of e.It is well-known that delimited control can make the two answer types distinct [DF89], and since answer types are needed to decide typability of programs, they must be integrated into the typing judgment.The other pair of types, µ β and µ α , are trail types, representing the composition of invocation contexts encountered before and after evaluation of e.We have seen that an invocation of a captured continuation can change the type of the trail, and since trail types are also relevant to typability of programs, they have to be integrated into the typing judgment.
Summing up the above discussion, we conclude that a fully expressive typing judgment for control and prompt must carry five types, as follows: We place the types in the same order as their appearance in the annotated CPS expression.That is, the first three types τ , µ α , and α correspond to the continuation of e, the next one µ β represents the trail required by e, and the last one β stands for the eventual value returned by e.We will hereafter call α and β initial and final answer types, and µ β and µ α initial and final trail types -be careful of the direction in which answer types and trail types change.
With the typing judgment specified, we can define the syntax of expression types of λ F (Figure 4).Expression types are formed with the integer type int and the arrow type τ 1 → τ 2 µ α α µ β β.Notice that the codomain of arrow types carries five components.These types represent the control effect of a function's body, and correspond exactly to the five types that appear in a typing judgment.
Comparison with Previous Work.In the type system of Kameyama and Yonezawa [KY08], a CPS-translated expression is typed in the following way: The typing is obviously not as flexible as ours, because the two trail types are equal.This constraint is imposed by the list representation of trails: even if an expression extends the trail during evaluation, the type of the trail stays the same.Thus, Kameyama and Yonezawa arrive at a typing judgment carrying four types, with the last one (ρ) representing the information of trails: Γ e : τ, α, β/ρ Correspondingly, they assign direct-style functions an arrow type of the form τ 1 → τ 2 , α, β/ρ.Typing Rules Figure 4: Type System of λ F 5.3.Typing Rules.Using the trail types and typing judgment from the previous subsections, we define the typing rules of λ F (Figure 4).As in the previous section, we elaborate the typing rules of variables, prompt, and control.
Variables.Recall that the CPS translation of variables is an η-expanded version of the standard translation.If we annotate the types of each subexpression, a translated variable would look like: We see duplicate occurrences of the answer type α and the trail type µ α .The duplication arises from the application k x t, and reflects the fact that a variable cannot change the answer type or the trail type.By a straightforward conversion from the annotated expression (second branch of ::) Figure 5: Auxiliary Relations into a typing judgment, we obtain rule (Var) in Figure 4.In general, when the subject of a typing judgment is a pure expression, the answer types and trail types both coincide.
Prompt.We next analyze the CPS translation of prompt, again with type annotations.
As e is a pure expression, we again have equal answer types α and trail types µ α for the whole expression.The initial trail type • and final answer type τ of e are determined by the application e k id () and k ( e k id ()), respectively.What is left is to ensure that the application of e to the identity continuation k id is type-safe.In our type system, we use a relation id-cont-type(τ, µ, τ ) to ensure this type safety.The relation holds when the type τ → µ → τ can be assigned to the identity continuation.The valid combination of τ , µ, and τ is derived from the definition of the identity continuation, repeated below.
When t is an empty trail () of type •, the return value of k id is v, which has type τ .Since the expected return type of k id is τ , we need the equality τ ≡ τ .
When t is a non-empty trail k of type τ 1 → µ → τ 1 , the return value of k id is the result of the application k v (), which has type τ 1 .Since the expected return type of k id is τ , we need the equality τ ≡ τ 1 .Furthermore, since k must accept v and () as arguments, we need the equalities τ ≡ τ 1 and µ ≡ •. 34:13 We define id-cont-type as an encoding of these constraints, and in the rule (Prompt), we use the premise id-cont-type(β, µ i , β ) to constrain the type of the continuation of e. Now, it is statically guaranteed that e will be safely evaluated in an empty context.
Control.Lastly, we apply the same method to control.Here is the annotated CPS translation: As the body e of control is evaluated in a prompt clause, we again have an empty initial trail type for e, and we know that the types γ, µ i , and γ must satisfy the id-cont-type relation.
What is left is to ensure that the composition of contexts in t @ (k 1 :: t 1 ) is type-safe.In our type system, we use a relation compatible(µ 1 , µ 2 , µ 3 ) to ensure this type safety.The relation holds when composing a context of type µ 1 and another context of type µ 2 results in a context of type µ 3 .Intuitively, the relation can be thought of as an addition over trail types (or equivalently, the type-level counterpart of append and cons).The valid combination of µ 1 , µ 2 , and µ 3 is derived from the definition of the @ and :: functions.
The first clause of @ and that of :: are straightforward: they tell us that the empty trail type • serves as the left and right identity of the addition.
The second clause of :: requires more careful reasoning.The return value of this case is the result of the application k v (k 1 :: t 1 ), which has type τ 1 .Since the expected return type of :: is τ 3 , we need the equality τ 1 ≡ τ 3 .Moreover, since k must accept v and k 1 :: t 1 as arguments, we need the equality τ 1 ≡ τ 3 , as well as the compatibility of µ 2 (type of k 1 ), µ 3 (type of t 1 ), and µ 1 (type of the trail expected by k).
We define compatible as an encoding of these constraints, and in the (Control) rule, we use two instances of this relation to constrain the type of contexts appearing in t @ (k 1 :: t 1 ).Among the two instances, the first one compatible((τ 1 → µ 1 τ 1 ), µ 2 , µ 0 ) states that consing k 1 to t 1 is type-safe, and the result has type µ 0 .The second one compatible(µ β , µ 0 , µ α ) states that appending t to k 1 :: t 1 is type-safe, and the result has type µ α , which is required by the continuation k of the whole control expression.
By designing (Control) and (Prompt) in this way, we have achieved the goal of this work: a type system that encodes all and only restrictions that arise from the CPS semantics of control and prompt.More precisely, we use the id-cont-type and compatible relations to enforce type-safe manipulation of contexts, while allowing the full flexibility in the type of contexts being manipulated.
A closer look at rule (Prompt) further reveals how prompt determines the trail type of its body.To spell out, the first and third occurrences of ρ in the premise mean that, if an expression e is surrounded by a prompt whose body is of type ρ, then the invocation contexts in the trail of e all have the same input / output type ρ. 5.4.Typing Heterogeneous Trails.We now show that example (2) from Section 2.2 is judged well-typed in λ F

5
. The well-typedness of the whole program largely relies on the well-typedness of the two control constructs, so let us look at the typing of these constructs: For brevity, we write µ 1 to mean int → bool → • string string, and µ 2 to mean int → • string.We can see how the trail type changes from empty (•), to one that refers to a future context (µ 1 ), and to one that mentions no further context (µ 2 ).In particular, µ 2 is the result of "adding" µ 1 and the type of b2s [.]; that is, the invocation of k 2 discharges the future context awaited by is0 [.].The trail type µ 2 serves as the final trail type of the body of the enclosing prompt, and as it allows us to establish the id-cont-type relation required by (Prompt), we can conclude that the whole program is well-typed.

Properties
The type system of λ F enjoys several pleasant properties.In this section, we discuss two properties with a complete proof and one property with a partial proof.6.1.Type Soundness.First, the type system is sound, that is, well-typed programs do not go wrong [Mil78].Following Wright and Felleisen [WF94], we prove type soundness via the preservation and progress theorems.Proof.The proof is by induction on the typing derivation6 .Note that, to prove this property, we need to define a set of typing rules for evaluation contexts.Proof.The proof is by induction on the typing derivation7 .The third alternative is commonly found in the progress property of effectful calculi [AK07, XBH + 20], meaning the presence of unhandled effects.

Syntax of Types
Proof.The statement is a direct implication of preservation and progress.Note that the empty final trail type means e does not have control effects.This is justified by the fact that the final trail type µ α in the typing rule (Control) must be non-empty, as the trail is composed of a non-empty trail of type τ 1 → µ 1 τ 1 .
6.2.Type Preservation of CPS Translation.Secondly, our CPS translation preserves typing, i.e., it converts a well-typed λ F expression into a well-typed λ C expression.To establish this theorem, we define the type system of λ C (Figure 6) and the CPS translation * on λ F types (Figure 7).Let us elaborate on rule (Case) in Figure 6, which is the only non-trivial typing rule.This rule is used to type the case analysis construct in the three auxiliary functions of the CPS translation, namely k id , @, and ::.A key feature of this rule is that it uses meta-level equality assumptions µ ≡ • and µ ≡ τ 1 → µ 1 τ 1 to type the two branches 8 .These 8 The use of equality assumptions in (Case) is inspired by dependent pattern matching [Coq92] available in dependently typed languages.Our case analysis is weaker than the dependent variant, in that the return type only depends on the type of the scrutinee, not on the scrutinee itself.For the formal definition, we refer the reader to our Agda implementation (lambdac.agda).
assumptions, together with the id-cont-type and compatible relations, fill in the gap between the expected and actual return types.As an illustration, let us elaborate the typing of k id : In the first branch, we see an inconsistency between the expected return type τ and the actual return type τ .However, by the typing rules defined in Figure 4, we know that k id is used only when the relation id-cont-type(τ, µ, τ ) holds.Moreover, by the definition of id-cont-type, if µ ≡ •, we have τ ≡ τ .The equality assumption µ ≡ • made available by rule (Case) allows us to derive τ ≡ τ and conclude that the first branch has the correct type.Similarly, in the second branch, we use the equality assumption µ ≡ τ 1 → µ 1 τ 1 to derive τ ≡ τ 1 , τ ≡ τ 1 , and µ 1 ≡ •, which imply the well-typedness of the application k v ().The @ and :: functions can be typed in an analogous way.Now we state the type preservation theorem.
Proof.The proof is by induction on the typing derivation9 .With the carefully designed rule for case analysis, we can prove the statement in a straightforward manner, as our type system is directly derived from the CPS translation.
From the above theorem, we can further derive the following corollary.
Corollary 6.5.An expression e is well-typed in λ F if and only if its CPS translation e is well-typed in λ C .
Proof.The "if" direction is trivial: as the type system is directly derived from the CPS translation, the statement holds by construction.The "only if" direction is exactly the statement of Theorem 6.4.
6.3.Termination of Evaluation.Lastly, we conjecture that our type system ensures termination of pure programs.
Conjecture 6.6 (Termination).If • e : τ • α • α, then there exists some value v such that e * v, where * is the reflexive, transitive closure of defined in Figure 1.
The statement is partially witnessed by a CPS interpreter of λ F implemented in Agda 10 .The interpreter shows that any well-typed λ F program evaluates to an Agda value under the big-step semantics derived from the CPS translation.To complete the proof, we must show that the big-step semantics underlying the interpreter and the small-step semantics defined for λ F are equivalent (i.e., they give us the same value).Our intuition is that the equivalence holds, but proving this requires non-trivial reasoning on continuations, and developing such a proof technique is beyond the main scope of this paper.The termination property, although not fully proved, seems to rely on the precise typing of invocation contexts.Indeed, in the existing type system by Kameyama and Yonezawa [KY08], it is possible to write a well-typed program that does not evaluate to a value.Here is a non-terminating program adapted from Kameyama and Yonezawa's example (we write e 1 ; e 2 as an abbreviation of (λ .e 2 ) e 1 ): We see that the two succeeding invocations of captured continuations result in duplication of control, leading to a looping behavior.
The well-typedness of the above program in Kameyama and Yonezawa's type system is due to the limited expressiveness of trail types.More precisely, their trail types are mere expression types, which carry no information about the type of contexts to be composed in the future.In our type system, on the other hand, trail types explicitly mention the type of future contexts.This prevents us from duplicating control infinitely, and allows us to statically reject the above looping program 11 .

Selective CPS Translation and Fine-grained Type System
In the CPS translation defined in Section 4, we converted every expression into a function that receives a continuation and a trail.When used as an implementation technique, such a whole-program translation would blow up the size of programs and lead to poor performance.A popular solution to this problem is to make the CPS translation selective [Nie01, KYD98, RMO09, AU17], that is, we only convert impure expressions into CPS, and keep pure expressions in direct style.
In this section, we present a selective CPS translation for control and prompt, as well as a corresponding type system.Unlike in the previous sections, here we first define the type system (Section 7.1) and then derive the CPS translation (Section 7.2).This is because defining a selective CPS translation requires a purity analysis, which in turn requires a type system.We show that, with the distinction between pure and impure expressions, we can still prove desired properties (Section 7.3).Furthermore, if we assume termination of well-typed programs, we can macro-express Danvy and Filinski's [DF90] shift operator using control and prompt (Section 7.4).7.1.Fine-grained Type System.We start by building a fine-grained type system (Figures 8 and 9, ignoring the shaded parts) that is suitable for defining a selective CPS translation.As we wish to use the type system to decide whether or not to CPS-translate an expression, we make a rigorous distinction between pure and impure expressions.We do this by introducing a special judgment Γ p e : τ for pure expressions, which does not carry answer types or trail types.This design is borrowed from earlier work on typed control operators [AK07, KY08], and reflects the fact that a pure expression can be evaluated independent of its surrounding context.As a corresponding change, we extend the syntax of Γ, x : τ 1 e : τ 2 µ α α µ β β e Γ e 1 : ( Γ e 1 e 2 : τ 2 µ γ γ µ β β λk. e 1 (λv 1 .e 2 (λv 2 .k Using the pure judgment and function types, we define the typing rules.There are several possible strategies for designing a fine-grained type system: • Define one rule for each combination of the purity of subexpressions [CA18].This allows us to design the most optimized CPS translation, but results in a large number of typing rules (for instance, we would need 2 3 = 8 rules for application).• Define one rule for each syntactic construct, and in each rule, perform a sophisticated computation over the effects of subexpressions [RMO09,IA19].This allows us to keep 34:19 Figure 9: Fine-grained Type System and Selective CPS Translation (continued) the type system concise, but makes it hard to see how each construct manipulates the answer type and trail type.• Define one or more rules for each syntactic construct depending on the granularity one wish to achieve, and include a rule for converting a pure expression into an impure one [MB11].This allows us to have a reasonably concise type system, at the cost of losing some optimization opportunities in the CPS translation.
Here we take the third approach to balance conciseness and efficiency.Among different constructs, values and prompt are syntactically classified as pure.Notice that we have two rules for abstractions, differing in the purity of the body expression.In particular, the (PAbs) rule is necessary for judging certain applications as pure ones.As we will see shortly, having pure applications allows us to eliminate multiple administrative redexes in the CPS translation.For prompt, on the other hand, we only have one rule where the body is an impure expression.This does not affect typability, as we can always cast a pure expression into an impure one via (Exp).The casting introduces some extra redexes in the CPS translation, but here we prioritize conciseness over efficiency.
An application is pure when the function e 1 , the argument e 2 , and the body of the function are all pure (PApp).The three rules for application, together with (Exp), give us the same expressiveness as having 8 rules as in the first approach mentioned above.Note that, without (PIApp), we would not be able to directly call a function that has a pure body but is itself an impure expression.
A control construct is always judged impure, but it has two rules differing in the purity of the captured continuation.The impure rule (IControl) is identical to the (Control) rule from Section 5.The pure rule (PControl) is simpler than the original rule in that it imposes no compatibility requirements.To see why we do not need those requirements, recall that the non-selective CPS translation of Fc. e extends the given trail.This is necessary for allowing the invocation context of c to be accessed by the control operators that reside in c.However, if c is pure, we know that its invocation does not involve any execution of control.This means, for a control operator that captures a pure continuation, we do not need to extend the trail.The absence of the compatibility requirements communicates the fact that no trail extension happens in this case.The equal initial and final trail types in the conclusion also reflect the stability of the trail.Having (PControl) could potentially be beneficial for optimizations, because extending a trail is done by recursively calling the cons function in the CPS translation.It would also help us simplify type error messages, as we can assign a pure function type (that does not mention answer types or trail types) to the captured continuation.7.2.Selective CPS Translation.Guided by the fine-grained type system, we define a selective CPS translation from λ F to λ C (shaded parts of Figures 8 and 9).The translation keeps pure expressions in direct-style, and turns impure expressions into a continuation-and trail-taking function.Unlike the translation defined in Section 4, the selective translation is defined on the typing derivation, because the information about purity is not generally available at the level of syntax.Therefore, we have one translation rule for each typing rule.
Let us take a closer look at the interesting cases.First, observe the three translation rules for application.In (PApp), we obtain a direct-style application e 1 e 2 .In (PIApp) and (IApp), we obtain a CPS function that uses the continuation k in a way that is consistent with the purity of the function body.
Second, compare the translation rules for control.In (PControl), we do not extend the trail as we do in (IControl), since we know the captured continuation is pure and thus cannot manipulate its invocation context.From an implementation perspective, this means the selective translation not only produces fewer applications involving continuations and trails, but also introduces fewer extensions of trails via consing and appending.
Thirdly and lastly, if a pure expression e is judged as impure via (Exp), it is translated to a CPS function that immediately calls the continuation k with the direct-style translation of e and the given trail t. 7.3.Properties.The fine-grained formulation of λ F enjoys similar properties to the original λ F .Specifically, the type system is sound, and the selective CPS translation is typepreserving.The termination property should also hold, although we only have a partial proof.
Theorem 7.1 (Type Soundness).If • p e : τ , then evaluation of e does not get stuck.
Proof.As in the original λ F , we prove type soundness via preservation and progress12 .
Proof.As before, we prove type preservation by induction on the typing derivation 13 .Note that we need to extend the type translation with a clause for pure function types: Notice also that the translation on pure expressions does not introduce new arrow types, meaning that pure expressions are kept in direct style.
Conjecture 7.3 (Termination).If Γ p e : τ , then there exists some value v such that e * v, where * is the reflexive, transitive closure of defined in Figure 1.
The statement is again partially witnessed by a CPS interpreter of the fine-grained λ F implemented in Agda14 .
7.4.Encoding of shift.Kameyama and Yonezawa [KY08] show that their type system allows a typed encoding of shift in terms of control and prompt.We show that this is possible in our fine-grained calculus as well, assuming that the termination conjecture actually holds.
Let us begin by comparing the reduction rules of shift and control: We see that the two rules differ in the presence of the delimiter surrounding the captured continuation.In other words, a continuation captured by shift is always pure, while a continuation captured by control may be impure.
There is a straightforward encoding of shift by control and prompt [BD05]: we simply wrap the continuation captured by control around prompt.
Sk. e = Fk 1 .e [λx.k 1 x /k] The encoding is well-typed in the fine-grained λ F .Specifically, the control construct can be typed by (PControl), because the captured continuation is a pure function.The absence of compatibility requirements, as well as the equal initial and final trail types, are consistent with the semantics of the shift operator: it does not modify the trail as general control may do.
Note that the encoding is not well-typed in the original λ F .The reason is that rule (Control) requires a compatibility relation that can never hold.Let us look at the derivation of the control construct: The instantiation of answer types and trail types is drawn from the typing constraints of control and prompt.By the definition of compatible, we know the trail type µ 0 in the first compatibility relation must be α → • α.By substituting this trail type for the µ 0 in the second compatibility relation, we obtain compatible(µ α , (α → • α), µ α ).This relation does not hold, as we prove in our Agda formalization 16 .As a consequence, we cannot close the above derivation.
In the fine-grained λ F , we can in fact simplify the encoding as follows: Sk. e = Fk.e where k is pure The simplified encoding says: a control operator that captures a pure continuation behaves the same as a shift operator.This can be proved by using the fact that the prompt operator is no-op when its body is a pure expression.Specifically, if e is pure, the expression e eventually evaluates to v (under the assumption that termination holds), and then to v by the reduction rule (P).Using this fact, we can rewrite the original encoding to Fk 1 .e [λx.k 1 x/k], and then to Sk. e by η-reduction and renaming.

Formalization in Agda
We have formalized λ F , λ C , and the CPS translations in the Agda proof assistant.In this section, we give the reader a high-level idea of how we formalized these artifacts.For the full formalization, we invite the reader to visit the following GitHub repository: https://github.com/YouyouCong/lmcs-artifactDefining Syntax and Typing Rules.Let us begin with the formalization of (original) λ F .Following the recipe of Altenkirch and Reus [AR99], we define λ F as an intrinsically-typed language.That is, we define the syntax and typing at once, and thus guarantee that we can only construct well-typed expressions.Before defining expressions, we define expression types and trail types as datatypes Ty and Tr.The type Reduce e e' means e e , and has one constructor for each reduction rule in Figure 1.For instance, RPrompt represents the rule v v. Notice that the two arguments to Reduce have the same type.This means, if we can define all the reduction rules as a constructor of Reduce, then we can be sure that reducing a well-typed expression produces an expression of the same type.Therefore, the definition of Reduce is essentially the proof of the preservation theorem (Theorem 6.1).
Defining CPS Translation.Now we proceed to the CPS translation.We formalize the target calculus λ C in a similar way to λ F , and define the CPS translation of types and expressions.In the above definition, CTy is the type of λ C types, and CVal is the type of λ C values.As we can see, the signature of cpse is exactly the statement of the type preservation theorem (Theorem 6.4).Thus, the definition of cpse serves as a proof of type preservation.

Related Work
Variations of Control Operators.There are four variants of delimited control operators in the style of control, differing in whether the operator keeps the surrounding delimiter, and whether it inserts a delimiter into the captured continuation [DPJS07].We have seen that the absence of the latter delimiter makes it possible to capture invocation contexts.The lack of the former delimiter, on the other hand, gives us access to metacontexts, i.e., contexts outside of the innermost delimiter.In the CPS translation, metacontexts are represented using a stack-like data structure, which is also called a trail in the literature [MB11].
As an orthogonal variation, some implementations of control operators provide prompt tags [GRR95,Kis12], allowing the programmer to specify the association between the control operator and the delimiter.Since tagged control operators make it possible to skip intervening delimiters, their CPS translation also involves a form of trails, containing the delimited contexts within individual delimiters.34:25 Type Systems for Control Operators.The CPS-based approach to designing type systems has been applied to three variants of delimited control operators, namely shift/reset [DF89, AK07], control/prompt [KY08], and shift0/reset0 [MB11].Among them, shift0 can capture metacontexts, hence its type system maintains a list of answer types, representing the return types of nesting delimiters [MB11].
The CPS approach gives us by default a type system where every expression is effectful, as in the original λ F .Such a type system is however impractical, as it rejects many programs that are in fact type-safe.For instance, we showed that the encoding of shift by control/prompt is ill-typed if control can only ever capture an impure continuation.It is also known that implementing the list prefix function using shift/reset requires continuations to be answer-type polymorphic [AK07], which basically means "pure".For this reason, many type systems for control operators employ a purity distinction as in the fine-grained λ F [AK07, KY08, MB11].
Selective CPS Translations and Fine-grained Type Systems.The idea of selectively CPS-translating programs based on a fine-grained type system has long been studied as a compilation technique for effectful languages.For example, Kim et al. [KYD98] use a selective CPS translation to reduce the overhead of ML exceptions.As a different example, Asai and Uehara [AU17] implement the shift and reset operators via a selective CPS translation.A particularly interesting result of the latter work is that, by treating shift-captured continuations as pure functions, we can significantly speed-up non-deterministic programs (such as the N-Queen puzzle).In the case of control, the impact of pure continuations may be even more remarkable, because they not only reduce continuation parameters, but also eliminate consing and appending of trails.
Algebraic Effects and Handlers.In the past decade, algebraic effects and handlers [BP15,PP09] have become a popular tool for handling delimited continuations.A prominent feature of effect handlers is that a captured continuation is used at the delimiter site.This makes it unnecessary to keep track of answer types in the type system, as we can decide within a handler whether the use of a continuation is consistent with the actual context.The irrelevance of answer types in turn makes the connection between the type system and CPS translation looser.Indeed, type systems of effect handlers [BP13, KLO13] existed before their CPS semantics [Lei17, HLAS17, HLA20].Also, type-preserving CPS translation of effect handlers is still an open problem in the community [HLA20].

Conclusion and Future Work
In this paper, we show how to derive a fully expressive type system for the control and prompt operators.The main idea is to identify all the typing constraints by analyzing a CPS translation, where trails are represented as a composition of functions.
The present study is part of a long-term project on formalizing delimited control facilities whose theory is not yet fully developed.In the rest of this section, we describe several directions for future work.
Polymorphism and Type Inference/Checking.Having established a principle for monomorphic typing, a natural next step is to extend the calculus with polymorphism.The combination of polymorphism and effects is a delicate issue, and often requires a value or purity restriction to restore type soundness [HL93,AK07].In the presence of control/prompt, we must further support abstraction over trail types, because otherwise we would not be able to call a function or continuation in different contexts.
After adding polymorphism, we would like to design an algorithm for type inference and type checking.We conjecture that answer types can be left implicit in the user program, because it is the case in a calculus featuring shift and reset [AK07].On the other hand, we anticipate that some of the trail types need to be explicitly given by the user, as it does not seem always possible to synthesize the intermediate trail types (µ 0 , τ 1 → µ 1 τ 1 , and µ 2 ) in the (Control) rule.
Implementation.With polymorphism and a type checking/inference algorithm, we are ready to develop a practical implementation of our control/prompt calculus.There are several approaches to implementing the dynamic behavior of the control operators.One way is to use the CPS translation defined in this paper, which eliminates the need for special runtime support.A more direct approach is to implement Fujii and Asai's [FA21] compiler, which is derived from a CPS interpreter by applying various program transformations.Once we have a language that we can play with, we will assess the usability of our language from the viewpoints of expressiveness and efficiency.
Equational Theory and Reflection.So far, the semantics of control and prompt has been given as a CPS translation and an abstract machine [Sha07,BDM15].In future work, we intend to develop an alternative semantics in the form of an equational theory.Such a semantics exists for shift/reset [KH03] and shift0/reset0 [Mat13], and is especially useful for compilation.For instance, it enables converting an optimization in a CPS compiler into a rewrite in a direct-style program [SF93].
An equational theory can further be refined into a reflection [SW97], where direct-style and CPS expressions are related by reduction rather than equation.Given the recent advance in the reflection for delimited control operators [BPS20, BPS21], we would naturally ask whether it is possible to extend the results to control/prompt.To answer this question, we need to first define a version of CPS translation that does not yield administrative redexes [Plo75,DN03], including the applications arising from consing and appending of trails.
Control0/Prompt0 and Shallow Effect Handlers.There is a variation of control and prompt, called control0 and prompt0, that remove the matching delimiter upon capturing of a continuation.We are currently formalizing a typed calculus of control0/prompt0, by combining the insights from the present work and previous study on shift0/reset0 [MB11].As shown by Piróg et al. [PPS19], there exists a pair of macro translations [Fel91] between control0/prompt0 and shallow effect handlers [HL18].This suggests that a good understanding of control0/prompt0 would serve as a stepping stone to a better implementation of shallow handlers.For example, establishing equational axioms for control0/prompt0 would help us establish similar axioms for shallow handlers, which would in turn be used to optimize languages with support for shallow handlers, such as Frank [LMM17] and Koka [Lei14].
[.]  + (Fk 2 .3 + (k 2 8)) (where[.]denotes a hole).The captured context is then reified into a function λx.x + (Fk 2 .3 + (k 2 8)), and evaluation shifts to the body 2 * (k 1 5), where k 1 is the reified continuation.After β-reducing the invocation of k 1 , we obtain another control in the evaluation position.This control captures the context 2 * (5 + [.]), which is a composition of two contexts: the addition context originally surrounding the control construct, and the multiplication context surrounding the invocation of k 1 .The context is then reified into a function λx. 2 * (5 + x), and evaluation shifts to the body 3 + (k 2 8), where k 2 is the reified continuation.By β-reducing the invocation of k 2 , we obtain the expression 3 + (2 * (5 + 8)), where the original delimited context, the invocation context of k 1 , and the invocation context of k 2 are all composed together.The expression returns the value 29 to the enclosing prompt clause, and the evaluation of the whole program finishes with 42.
Theorem 6.2 (Progress).If • e : τ µ α α µ β β, then either (i) e is a value, (ii) e takes a step, or (iii) e is a stuck term of the form F [Fk. e ].