mirror of
https://github.com/dhil/phd-dissertation
synced 2026-03-13 11:08:25 +00:00
Restore consistency between control/prompt and shift/reset example.
This commit is contained in:
253
thesis.tex
253
thesis.tex
@@ -865,124 +865,30 @@ just as a delimited abortive continuation is conceivable.
|
||||
A composable continuation is also known as a `functional' continuation
|
||||
in the literature.
|
||||
|
||||
% % \citeauthor{Reynolds93} has written a historical account of the
|
||||
% % various early discoveries of continuations~\cite{Reynolds93}.
|
||||
|
||||
% In the literature the term ``continuation'' is often accompanied by a
|
||||
% qualifier such as full~\cite{JohnsonD88}, partial~\cite{JohnsonD88},
|
||||
% abortive, escape, undelimited, delimited, composable, or functional.
|
||||
% %
|
||||
% Some of these qualifiers are synonyms, and hence redundant, e.g. the
|
||||
% terms ``full'' and ``undelimited'' refer to the same notion of
|
||||
% continuation, likewise the terms ``partial'' and ``delimited'' mean
|
||||
% the same thing, the notions of ``abortive'' and ``escape'' are
|
||||
% interchangeable too, and ``composable'' and ``functional'' also refer
|
||||
% to the same notion.
|
||||
% %
|
||||
|
||||
% Thus the peloton of distinct continuation notions can be pruned to
|
||||
% ``undelimited'', ``delimited'', ``abortive'', and ``composable''.
|
||||
% %
|
||||
% The first two notions concern the introduction of continuations, that
|
||||
% is how continuations are captured. Dually, the latter two notions
|
||||
% concern the elimination of continuations, that is how continuations
|
||||
% interact with the enclosing context.
|
||||
% %
|
||||
% Consequently, it is not meaningful to contrast, say, ``undelimited''
|
||||
% with ``abortive'' continuations, because they are orthogonal notions.
|
||||
% %
|
||||
% A common confusion in the literature is to conflate ``undelimited''
|
||||
% continuations with ``abortive'' continuations.
|
||||
% % Similarly, often times ``composable'' is taken to imply ``delimited''.
|
||||
% However, it is perfectly possible to conceive of a continuation that
|
||||
% is undelimited but not abortive.
|
||||
% %
|
||||
% % An educated guess as to why this confusion occurs in the literature
|
||||
% % may be that it is due to the introduction
|
||||
|
||||
% To make each notion of continuation concrete I will present its
|
||||
% characteristic reduction rule. To facilitate this presentation I will
|
||||
% make use of an abstract control operator $\CC$ to perform an abstract
|
||||
% capture of continuations, i.e. informally $C\,k.M$ is to be understood
|
||||
% as a syntactic construct that captures the continuation and reifies it
|
||||
% as a function which it binds to $k$ in the computation $M$. The
|
||||
% precise extent of the capture will be given by the characteristic
|
||||
% reduction rule. I will also make use of an abstract control delimiter
|
||||
% $\Delim{-}$. The term $\Delim{M}$ encloses the computation $M$ in a
|
||||
% syntactically identifiable marker. For the intent and purposes of this
|
||||
% presentation enclosing a value in a delimiter is an idempotent
|
||||
% operation, i.e. $\Delim{V} \reducesto V$. I will write $\EC$ to
|
||||
% denote an evaluation context~\cite{Felleisen87}.
|
||||
|
||||
% \paragraph{Undelimited continuation}
|
||||
% %
|
||||
% \[
|
||||
% \EC[\CC\,k.M] \reducesto \EC[M[(\lambda x.\EC[x])/k]]
|
||||
% \]
|
||||
% %
|
||||
% \begin{derivation}
|
||||
% & 3 * (\CC\,k. 2 + k\,(k\,1))\\
|
||||
% \reducesto& \reason{captures the context $k = 3 * [~]$}\\
|
||||
% & 3 * (2 + k\,(k~1))[(\lambda x. 3 * x)/k]\\
|
||||
% =& \reason{substitution}\\
|
||||
% & 3 * (2 + (\lambda x. 3 * x)((\lambda x. 3 * x)\,1))\\
|
||||
% \reducesto& \reason{$\beta$-reduction}\\
|
||||
% & 3 * (2 + (\lambda x. 3 * x)(3 * 1))\\
|
||||
% \reducesto& \reason{$\beta$-reduction}\\
|
||||
% & 3 * (2 + (\lambda x. 3 * x)\,3)\\
|
||||
% \reducesto^4& \reason{$\beta$-reductions}\\
|
||||
% & 33
|
||||
% \end{derivation}
|
||||
|
||||
% \paragraph{Delimited continuation}
|
||||
% %
|
||||
% \[
|
||||
% \Delim{\EC[\CC\,k.M]} \reducesto \Delim{M[(\lambda x.\Delim{\EC[x]})/k]}
|
||||
% \]
|
||||
% %
|
||||
% \[
|
||||
% \Delim{\EC[\CC\,k.M]} \reducesto M[(\lambda x.\Delim{\EC[x]})/k]
|
||||
% \]
|
||||
|
||||
% \paragraph{Abortive continuation} An abortive continuation discards the current context.Like delimited continuations, an
|
||||
% abortive continuation is accompanied by a delimiter. The
|
||||
% characteristic property of an abortive continuation is that it
|
||||
% discards its invocation context up to its enclosing delimiter.
|
||||
% %
|
||||
% \[
|
||||
% \EC[k\,V] \reducesto V, \quad \text{where } k = (\lambda x. \keyw{abort}\;x).
|
||||
% \]
|
||||
% %
|
||||
% Consequently, composing an abortive continuation with itself is
|
||||
% meaningless, e.g. in $k (k\,V)$ the innermost application erases the
|
||||
% outermost application.
|
||||
|
||||
% \paragraph{Composable continuation} The defining characteristic of a
|
||||
% composable continuation is that it composes the captured context with
|
||||
% current context, i.e.
|
||||
% %
|
||||
% \[
|
||||
% \EC[k\,V] \reducesto \EC[\EC'[V]], \quad \text{where } k = (\lambda x. \EC'[x])
|
||||
% \]
|
||||
|
||||
% Escape continuations, undelimited continuations, delimited
|
||||
% continuations, composable continuations.
|
||||
|
||||
% Downward and upward use of continuations.
|
||||
|
||||
\section{Controlling continuations}
|
||||
\label{sec:controlling-continuations}
|
||||
As suggested in the previous section, the design space for
|
||||
continuation is rich. This richness is to an extent reflected by the
|
||||
considerable amount of control operators that appear in the literature
|
||||
large amount of control operators that appear in the literature
|
||||
and in practice.
|
||||
%
|
||||
The purpose of this section is to survey a considerable subset of the
|
||||
first-class \emph{sequential} control operators that occur in the
|
||||
literature and in practice. Control operators for parallel programming
|
||||
will not be considered here.
|
||||
%
|
||||
Table~\ref{tbl:classify-ctrl} provides a classification of a
|
||||
non-exhaustive list of first-class control operators.
|
||||
|
||||
It is worth remarking that a \emph{first-class} control operator is
|
||||
typically not itself a first-class citizen, rather, it means that the
|
||||
reified continuation is a first-class citizen.
|
||||
Note that a \emph{first-class} control operator is typically not
|
||||
itself a first-class citizen, rather, the label `first-class' means
|
||||
that the reified continuation is a first-class object. Control
|
||||
operators that reify the current continuation can be made first-class
|
||||
by enclosing them in a $\lambda$-abstraction. Obviously, this trick
|
||||
does not work for operators that reify the caller continuation.
|
||||
|
||||
To study the control operators we will make use of a small base
|
||||
language.
|
||||
%
|
||||
\begin{table}
|
||||
\centering
|
||||
@@ -1028,7 +934,7 @@ reified continuation is a first-class citizen.
|
||||
|
||||
\paragraph{A small calculus for control}
|
||||
%
|
||||
To look at control we will a simply typed fine-grain call-by-value
|
||||
To look at control we will use a simply typed fine-grain call-by-value
|
||||
calculus. Although, we will sometimes have to discard the types, as
|
||||
many of the control operators were invented and studied in a untyped
|
||||
setting. The calculus is essentially the same as the one used in
|
||||
@@ -1063,6 +969,17 @@ primitive $\Continue$.
|
||||
{\typ{\Gamma}{V : A} \\ \typ{\Gamma}{W : \Cont\,\Record{A;B}}}
|
||||
{\typ{\Gamma}{\Continue~W~V : B}}
|
||||
\end{mathpar}
|
||||
%
|
||||
Although, it is convenient to treat continuation application specially
|
||||
for operational inspection, it is rather cumbersome to do so when
|
||||
studying encodings of control operators. Therefore, to obtain the best
|
||||
of both worlds, the control operators will reify their continuations
|
||||
as first-class functions, whose body is $\Continue$-expression. To
|
||||
save some ink, we will use the following notation.
|
||||
%
|
||||
\[
|
||||
\qq{\cont_{\EC}} \defas \lambda x. \Continue~\cont_{\EC}~x
|
||||
\]
|
||||
|
||||
\subsection{Undelimited control operators}
|
||||
%
|
||||
@@ -1432,9 +1349,13 @@ continuation with the then-current continuation.
|
||||
$\FelleisenC$.
|
||||
%
|
||||
\[
|
||||
\sembr{\FelleisenC} \defas \lambda m.\FelleisenF\,(\lambda k. m\,(\lambda v.\FelleisenF\,(\lambda\_.\Continue~k~v)))
|
||||
\sembr{\FelleisenC} \defas \lambda m.\FelleisenF\,(\lambda k. m\,(\lambda v.\FelleisenF\,(\lambda\_.k~v)))
|
||||
\]
|
||||
%
|
||||
The first application of $\FelleisenF$ has the effect of aborting the
|
||||
current continuation, whilst the second application of $\FelleisenF$
|
||||
aborts the invocation context.
|
||||
|
||||
\citet{FelleisenFDM87} also postulate that $\FelleisenC$ cannot express $\FelleisenF$.
|
||||
|
||||
\paragraph{\citeauthor{Landin98}'s J operator}
|
||||
@@ -1559,11 +1480,16 @@ translate $\J$ to a language with $\JI$ as follows.
|
||||
\sembr{\J} \defas (\lambda k.\lambda f.\lambda x.\Continue\;k\,(f\,x))\,(\JI)
|
||||
\]
|
||||
%
|
||||
Strictly speaking in our setting this encoding is not faithful,
|
||||
because we do not treat continuations as first-class functions,
|
||||
meaning the types are not going to match up. An application of the
|
||||
left hand side returns a continuation object, whereas an application
|
||||
of the right hand side returns a continuation function.
|
||||
The term $\JI$ captures the caller continuation, which gets bound to
|
||||
$k$. The shape of the residual term is as expected: when $\sembr{\J}$
|
||||
is applied to a function, it returns another function, which when
|
||||
applied ultimately invokes the captured continuation.
|
||||
%
|
||||
% Strictly speaking in our setting this encoding is not faithful,
|
||||
% because we do not treat continuations as first-class functions,
|
||||
% meaning the types are not going to match up. An application of the
|
||||
% left hand side returns a continuation object, whereas an application
|
||||
% of the right hand side returns a continuation function.
|
||||
|
||||
Let us end by remarking that the J operator is expressive enough to
|
||||
encode a familiar control operator like $\Callcc$~\cite{Thielecke98}.
|
||||
@@ -1576,11 +1502,16 @@ encode a familiar control operator like $\Callcc$~\cite{Thielecke98}.
|
||||
syntactically embedded using callcc.
|
||||
%
|
||||
\[
|
||||
\sembr{\lambda x.M} \defas \lambda x.\Callcc\,(\lambda k.\sembr{M}[\J \mapsto \lambda f.\lambda y. \Continue~k~(f\,y)])
|
||||
\sembr{\lambda x.M} \defas \lambda x.\Callcc\,(\lambda k.\sembr{M}[\J \mapsto \lambda f.\lambda y. k~(f\,y)])
|
||||
\]
|
||||
% %
|
||||
\dhil{I am sort of torn between whether to treat continuations as
|
||||
first-class functions\dots}
|
||||
%
|
||||
The key point here is that $\lambda$-abstractions are not translated
|
||||
homomorphically. The occurrence of $\Callcc$ immediately under the
|
||||
binder reifies the current continuation of the function, which is the
|
||||
precisely the caller continuation in the body $M$. In $M$ the symbol
|
||||
$\J$ is substituted with a function that simulates $\J$ by
|
||||
post-composing the captured continuation with the function argument
|
||||
provided to $\J$.
|
||||
|
||||
\subsection{Delimited control operators}
|
||||
%
|
||||
@@ -1726,6 +1657,10 @@ The prompt remains in place after the reification, and thus any
|
||||
subsequent application of $\Control$ will be delimited by the same
|
||||
prompt.
|
||||
%
|
||||
Presenting $\Control$ as a binding form may conceal the fact that it
|
||||
is same as $\FelleisenF$. However, the presentation here is close to
|
||||
\citeauthor{SitaramF90}'s presentation, which in turn is close to
|
||||
actual implementations of $\Control$.
|
||||
|
||||
The static semantics of control and prompt were absent in
|
||||
\citeauthor{Felleisen88}'s original treatment.
|
||||
@@ -1801,40 +1736,62 @@ To illustrate $\Prompt$ and $\Control$ in action, let us consider a
|
||||
few simple examples.
|
||||
%
|
||||
\begin{derivation}
|
||||
& 1 + \Prompt~2 + (\Control~k.\Continue~k~(\Continue~k~0))\\
|
||||
\reducesto^+& \reason{Capture $\EC = 2 + [\,]$}\\
|
||||
& 1 + \Prompt~\Continue~\cont_{\EC}~(\Continue~\cont_{\EC]}~0))\,\\
|
||||
& 1 + \Prompt~2 + (\Control~k.3 + k~0) + (\Control~k'.k'~4)\\
|
||||
\reducesto^+& \reason{Capture $\EC = 2 + [\,] + (\Control~k'.k'~4)$}\\
|
||||
& 1 + \Prompt~3+\Continue~\cont_{\EC}~0\\
|
||||
\reducesto & \reason{Resume with 0}\\
|
||||
& 1 + \Prompt~\Continue~\cont_{\EC}~(2 + 0)\\
|
||||
\reducesto^+ & \reason{Resume with 2}\\
|
||||
& 1 + \Prompt~2 + 2\\
|
||||
& 1 + \Prompt~3 + (2 + 0) + (\Control~k'.k'~4)\\
|
||||
\reducesto^+ & \reason{Capture $\EC' = 5 + [\,]$}\\
|
||||
& 1 + \Prompt~\Continue~\cont_{\EC'}~4\\
|
||||
\reducesto^+ & \reason{Resume with 4}\\
|
||||
& 1 + \Prompt~5 + 4\\
|
||||
\reducesto^+ & \reason{\slab{Value} rule}\\
|
||||
& 1 + 4 \reducesto 5
|
||||
& 1 + 9 \reducesto 10
|
||||
\end{derivation}
|
||||
%
|
||||
The continuation captured by the application of $\Control$ is
|
||||
The continuation captured by the either application of $\Control$ is
|
||||
oblivious to the continuation $1 + [\,]$ of $\Prompt$. Since the
|
||||
captured continuation is composable it returns to its call site. The
|
||||
first invocation of the continuation $k$ returns the value 2, which is
|
||||
provided as the argument to the second invocation of $k$, resulting in
|
||||
the value $4$. The prompt $\Prompt$ gets eliminated when the
|
||||
computation constituent of $\Prompt$ has been reduced to the value
|
||||
$4$, which is (implicitly) supplied to the continuation of $\Prompt$.
|
||||
invocation of the captured continuation $k$ returns the value 0, but
|
||||
splices the captured context into the context $3 + [\,]$. The second
|
||||
application of $\Control$ captures the new context up to the
|
||||
delimiter. The continuation is immediately applied to the value 4,
|
||||
which causes the captured context to be reinstated with the value 4
|
||||
plugged in. Ultimately the delimited context reduces to the value $9$,
|
||||
after which the prompt $\Prompt$ gets eliminated, and the continuation
|
||||
of the $\Prompt$ is applied to the value $9$, resulting in the final
|
||||
result $10$.
|
||||
|
||||
Let us consider a slight variation of the previous example.
|
||||
%
|
||||
\begin{derivation}
|
||||
& 1 + \Prompt~2 + (\Control~k.\Continue~k~0) + (\Control~k'. 0)\\
|
||||
\reducesto^+& \reason{Capture $\EC = 2 + [\,] + (\Control~k'.0)$}\\
|
||||
& 1 + \Prompt~\Continue~\cont_{\EC}~0\\
|
||||
& 1 + \Prompt~2 + (\Control~k.3 + k~0) + (\Control~k'.4)\\
|
||||
\reducesto^+& \reason{Capture $\EC = 2 + [\,] + (\Control~k'.4)$}\\
|
||||
& 1 + \Prompt~3+\Continue~\cont_{\EC}~0\\
|
||||
\reducesto & \reason{Resume with 0}\\
|
||||
& 1 + \Prompt~2 + 0 + (\Control~k'. 0)\\
|
||||
\reducesto^+ & \reason{Capture $\EC' = 2 + [\,]$}\\
|
||||
& 1 + \Prompt~0 \\
|
||||
\reducesto & \reason{\slab{Value} rule}\\
|
||||
& 1 + 0 \reducesto 1
|
||||
& 1 + \Prompt~3 + (2 + 0) + (\Control~k'.4)\\
|
||||
\reducesto^+ & \reason{Capture $\EC' = 5 + [\,]$}\\
|
||||
& 1 + \Prompt~4\\
|
||||
\reducesto^+ & \reason{\slab{Value} rule}\\
|
||||
& 1 + 4 \reducesto 5
|
||||
\end{derivation}
|
||||
%
|
||||
Here the computation constituent of the second application of
|
||||
$\Control$ drops the captured continuation, which has the effect of
|
||||
erasing the previous computation, ultimately resulting in the value
|
||||
$5$ rather than $10$.
|
||||
% \begin{derivation}
|
||||
% & 1 + \Prompt~2 + (\Control~k.\Continue~k~0) + (\Control~k'. 0)\\
|
||||
% \reducesto^+& \reason{Capture $\EC = 2 + [\,] + (\Control~k'.0)$}\\
|
||||
% & 1 + \Prompt~\Continue~\cont_{\EC}~0\\
|
||||
% \reducesto & \reason{Resume with 0}\\
|
||||
% & 1 + \Prompt~2 + 0 + (\Control~k'. 0)\\
|
||||
% \reducesto^+ & \reason{Capture $\EC' = 2 + [\,]$}\\
|
||||
% & 1 + \Prompt~0 \\
|
||||
% \reducesto & \reason{\slab{Value} rule}\\
|
||||
% & 1 + 0 \reducesto 1
|
||||
% \end{derivation}
|
||||
%
|
||||
The continuation captured by the first application of $\Control$
|
||||
contains another application of $\Control$. The application of the
|
||||
continuation immediate reinstates the captured context filling the
|
||||
@@ -1936,21 +1893,21 @@ perspective, let us revisit the second control/prompt example with
|
||||
shift/reset instead.
|
||||
%
|
||||
\begin{derivation}
|
||||
& 1 + \reset{2 + (\shift\;k.3 + k\,0) + (\shift\;k'.0)}\\
|
||||
\reducesto^+& \reason{Capture $\EC = 2 + [\,] + (\shift\;k.0)$}\\
|
||||
& 1 + \reset{2 + (\shift\;k.3 + k\,0) + (\shift\;k'.4)}\\
|
||||
\reducesto^+& \reason{Capture $\EC = 2 + [\,] + (\shift\;k.4)$}\\
|
||||
& 1 + \reset{\Continue~\cont_{\EC}~0}\\
|
||||
\reducesto & \reason{Resume with 0}\\
|
||||
& 1 + \reset{3 + \reset{2 + 0 + (\shift\;k'. 0)}}\\
|
||||
& 1 + \reset{3 + \reset{2 + 0 + (\shift\;k'. 4)}}\\
|
||||
\reducesto^+ & \reason{Capture $\EC' = 2 + [\,]$}\\
|
||||
& 1 + \reset{3 + \reset{0}} \\
|
||||
& 1 + \reset{3 + \reset{4}} \\
|
||||
\reducesto^+ & \reason{\slab{Value} rule}\\
|
||||
& 1 + \reset{3} \reducesto^+ 4 \\
|
||||
& 1 + \reset{7} \reducesto^+ 8 \\
|
||||
\end{derivation}
|
||||
%
|
||||
Contrast this result with the result $1$ obtained when using
|
||||
Contrast this result with the result $5$ obtained when using
|
||||
control/prompt. In essence the insertion of a new reset after
|
||||
resumption has the effect of remembering the local context of the
|
||||
first continuation invocation.
|
||||
previous continuation invocation.
|
||||
|
||||
This difference naturally raises the question whether shift/reset and
|
||||
control/prompt are interdefinable or exhibit essential expressivity
|
||||
|
||||
Reference in New Issue
Block a user