Browse Source

Restore consistency between control/prompt and shift/reset example.

master
Daniel Hillerström 5 years ago
parent
commit
a4e504e24b
  1. 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 A composable continuation is also known as a `functional' continuation
in the literature. 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} \section{Controlling continuations}
\label{sec:controlling-continuations} \label{sec:controlling-continuations}
As suggested in the previous section, the design space for As suggested in the previous section, the design space for
continuation is rich. This richness is to an extent reflected by the 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. 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 Table~\ref{tbl:classify-ctrl} provides a classification of a
non-exhaustive list of first-class control operators. 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} \begin{table}
\centering \centering
@ -1028,7 +934,7 @@ reified continuation is a first-class citizen.
\paragraph{A small calculus for control} \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 calculus. Although, we will sometimes have to discard the types, as
many of the control operators were invented and studied in a untyped many of the control operators were invented and studied in a untyped
setting. The calculus is essentially the same as the one used in 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}{V : A} \\ \typ{\Gamma}{W : \Cont\,\Record{A;B}}}
{\typ{\Gamma}{\Continue~W~V : B}} {\typ{\Gamma}{\Continue~W~V : B}}
\end{mathpar} \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} \subsection{Undelimited control operators}
% %
@ -1432,9 +1349,13 @@ continuation with the then-current continuation.
$\FelleisenC$. $\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$. \citet{FelleisenFDM87} also postulate that $\FelleisenC$ cannot express $\FelleisenF$.
\paragraph{\citeauthor{Landin98}'s J operator} \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) \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 Let us end by remarking that the J operator is expressive enough to
encode a familiar control operator like $\Callcc$~\cite{Thielecke98}. 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. 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} \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 subsequent application of $\Control$ will be delimited by the same
prompt. 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 The static semantics of control and prompt were absent in
\citeauthor{Felleisen88}'s original treatment. \citeauthor{Felleisen88}'s original treatment.
@ -1801,40 +1736,62 @@ To illustrate $\Prompt$ and $\Control$ in action, let us consider a
few simple examples. few simple examples.
% %
\begin{derivation} \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}\\ \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}\\ \reducesto^+ & \reason{\slab{Value} rule}\\
& 1 + 4 \reducesto 5
& 1 + 9 \reducesto 10
\end{derivation} \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 oblivious to the continuation $1 + [\,]$ of $\Prompt$. Since the
captured continuation is composable it returns to its call site. 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. Let us consider a slight variation of the previous example.
% %
\begin{derivation} \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}\\ \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} \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$ The continuation captured by the first application of $\Control$
contains another application of $\Control$. The application of the contains another application of $\Control$. The application of the
continuation immediate reinstates the captured context filling 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. shift/reset instead.
% %
\begin{derivation} \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}\\ & 1 + \reset{\Continue~\cont_{\EC}~0}\\
\reducesto & \reason{Resume with 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 + [\,]$}\\ \reducesto^+ & \reason{Capture $\EC' = 2 + [\,]$}\\
& 1 + \reset{3 + \reset{0}} \\
& 1 + \reset{3 + \reset{4}} \\
\reducesto^+ & \reason{\slab{Value} rule}\\ \reducesto^+ & \reason{\slab{Value} rule}\\
& 1 + \reset{3} \reducesto^+ 4 \\
& 1 + \reset{7} \reducesto^+ 8 \\
\end{derivation} \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 control/prompt. In essence the insertion of a new reset after
resumption has the effect of remembering the local context of the 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 This difference naturally raises the question whether shift/reset and
control/prompt are interdefinable or exhibit essential expressivity control/prompt are interdefinable or exhibit essential expressivity

Loading…
Cancel
Save