Table of Links
-
Translating To Sequent Calculus
-
Evaluation Within a Context
-
Insights
5.1 Evaluation Contexts are First Class
5.3 Let-Bindings are Dual to Control Operators
5.4 The Case-of-Case Transformation
5.5 Direct and Indirect Consumers
-
Conclusion, Data Availability Statement, and Acknowledgments
A. The Relationship to the Sequent Calculus
C. Operational Semantics of label/goto
5.3 Let-Bindings are Dual to Control Operators
The label construct in Fun is translated to a π-binding in Core. Also, when considering the typing rule for label πΌ {π‘ } in Section 4.1, we can see that it directly corresponds to typing a π-binding with the label πΌ being the bound covariable. Similarly, a let-binding is translated to a πΛ-binding and typing a let-binding in Fun closely corresponds to typing a πΛ-term in Core. This way, labels and let-bindings are dual to each other, the same way π and πΛ are. The duality can be extended to other control operators such as call/cc.
As it turns out, the label construct is very closely related to call/cc. There are in fact only two differences. First, label πΌ {π‘ } has the binder πΌ for the continuation built into the construct, just as the variation of call/cc named let/cc (which Reynolds [1972] called escape). The second, and more important difference is that the invocation of the continuation captured by label πΌ {π‘ } happens through an explicit language construct goto(π‘; πΌ). This makes it easy to give a translation to Core as we can simply insert another π-binding to discard the remaining continuation at exactly the place where the captured continuation is invoked. In contrast, with call/cc and let/cc the continuation is applied in the same way as a normal function, making it necessary to redefine the variable the captured continuation is bound to when translating to Core. This obscures the duality to let-bindings which is so evident for label and goto.
To see this, here is a translation of let/cc π π‘ to Core
[let/cc π π‘] β ππΌ.β¨cocase {ap(π₯, π½) β β¨π₯ | πΌβ©} | ππ. Λ β¨[π‘] | πΌβ©β©
The essence of the translation still is that the current continuation is captured by the outer π and bound to πΌ. But now we also have to transform this πΌ into a function (the cocase here) which discards its context (here bound to π½) and bind this function to π, which is done using πΛ. For call/cc, the duality is even more obscured, as there the binder for the continuation is hidden in the function which call/cc is applied to. For the translation, this function must then be applied to the above cocase and the captured continuation πΌ, resulting in the following term (cf. also [Miquey 2019]).
[call/cc π] β ππΌ.β¨[π ] | ap(cocase {ap(π₯, π½) β β¨π₯ | πΌβ©}, πΌ)β©
Other control operators for undelimited continuations can be translated in a similar way. For example, consider Felleisenβs C [Felleisen et al. 1987]. The difference to call/cc is that C discards the current continuation if it is not invoked somewhere in the term C is applied to, whereas call/cc leaves it in place and thus behaves as a no-op if the captured continuation is never invoked. The only change that needs to be made in the translation to Core is that the top-level continuation β has to be used for the outer cut instead of using the captured continuation. This is most easily seen for a variation of C which has the binder for the continuation built into the operator and where the invocation of the continuation is explicit, similar to label/goto. Calling this variation labelC, we obtain the following translation
[labelC πΌ {π‘ }] β ππΌ.β¨[π‘] | ββ©
Here the duality to let-bindings is evident again. The translation for C itself is then obtained in the same way as for call/cc
[C π ] β ππΌ.β¨[π ] | ap(cocase {ap(π₯, π½) β β¨π₯ | πΌβ©}, β)β©
5.4 The Case-of-Case Transformation
One important transformation in functional compilers is the case-of-case transformation. Maurer et al. [2017] give the following example of this transformation. The term
n
ifΒ (ifΒ π1Β thenΒ π2Β elseΒ π3)Β thenΒ π4Β elseΒ π5
n
can be replaced by the term
n
ifΒ π1Β thenΒ (ifΒ π2Β thenΒ π4Β elseΒ π5)Β elseΒ (ifΒ π3Β thenΒ π4Β elseΒ π5).
n
Logicians call these kinds of transformations commutative conversions, and they play an important role in the study of the sequent calculus. But as Maurer et al. [2017] show, they are also important for compiler writers who want to generate efficient code.
n
In the πππΛ-calculus, commuting conversions donβt have to be implemented as a special compiler pass. They fall out for free as a special instance of π-reductions! Let us illustrate this point by translating Maurer et al.βs example into the πππΛ-calculus. First, let us translate the two examples using pattern-matching syntax:
n
Let us now translate these two terms into the πππΛ-calculus:
n
n
We can see that just by reducing all of the underlined redexes we reduce both of these examples to the same term.
:::info
Authors:
(1) David Binder, University of TΓΌbingen, Germany;
(2) Marco Tzschentke, University of TΓΌbingen, Germany;
(3) Marius Muller, University of TΓΌbingen, Germany;
(4) Klaus Ostermann, University of TΓΌbingen, Germany.
:::
:::info
This paper is available on arxiv under CC BY 4.0 license.
:::