Browse Source

State example with delimited control

master
Daniel Hillerström 5 years ago
parent
commit
4ece98ba21
  1. 23
      thesis.bib
  2. 125
      thesis.tex

23
thesis.bib

@ -822,6 +822,18 @@
year = {2012} year = {2012}
} }
@inproceedings{VazouL16,
author = {Niki Vazou and
Daan Leijen},
title = {From Monads to Effects and Back},
booktitle = {{PADL}},
series = {{LNCS}},
volume = {9585},
pages = {169--186},
publisher = {Springer},
year = {2016}
}
@inproceedings{PauwelsSM19, @inproceedings{PauwelsSM19,
author = {Koen Pauwels and author = {Koen Pauwels and
Tom Schrijvers and Tom Schrijvers and
@ -1517,7 +1529,7 @@
year = {1994} year = {1994}
} }
# Simulation of delimited control using undelimited control
# Simulation of delimited control using undelimited control & monadic reflection
@inproceedings{Filinski94, @inproceedings{Filinski94,
author = {Andrzej Filinski}, author = {Andrzej Filinski},
title = {Representing Monads}, title = {Representing Monads},
@ -1527,6 +1539,13 @@
year = {1994} year = {1994}
} }
@phdthesis{Filinski96,
author = {Andrzej Filinski},
title = {Controlling Effects},
school = {Carnegie Mellon University},
year = {1996}
}
# Landin's J operator # Landin's J operator
@article{Landin65, @article{Landin65,
author = {Peter J. Landin}, author = {Peter J. Landin},
@ -3247,4 +3266,4 @@
number = {1}, number = {1},
pages = {1--32}, pages = {1--32},
year = {2003} year = {2003}
}
}

125
thesis.tex

@ -449,8 +449,11 @@ Builtin mutable state comes with three operations.
% %
The first operation \emph{initialises} a new mutable state cell; the The first operation \emph{initialises} a new mutable state cell; the
second operation \emph{gets} the value of a given state cell; and the second operation \emph{gets} the value of a given state cell; and the
third operation \emph{puts} a new value into a given state cell.
%
third operation \emph{puts} a new value into a given state cell. It is
important to note here retrieving contents of the state cell is an
idempotent action, whilst modifying the contents is a destructive
action.
The following function illustrates a use of the get and put primitives The following function illustrates a use of the get and put primitives
to manipulate the contents of some global state cell $st$. to manipulate the contents of some global state cell $st$.
% %
@ -488,9 +491,10 @@ the state cell.
\] \]
% %
State-passing is a global phenomenon that requires us to rewrite the State-passing is a global phenomenon that requires us to rewrite the
signatures of all functions that makes use of state, i.e. in order to
endow an $n$-ary function that returns some value of type $R$ with
state $S$ we have to transform its type as follows.
signatures (and their implementations) of all functions that makes use
of state, i.e. in order to endow an $n$-ary function that returns some
value of type $R$ with state $S$ we have to transform its type as
follows.
% %
\[ \[
\val{A_1 \to \cdots \to A_n \to R}_S \val{A_1 \to \cdots \to A_n \to R}_S
@ -499,22 +503,84 @@ state $S$ we have to transform its type as follows.
% %
\subsubsection{Opaque state-passing with delimited control} \subsubsection{Opaque state-passing with delimited control}
% %
Delimited control appears during the late 80s in different
forms~\cite{SitaramF90,DanvyF89}.
%
There are several different forms of delimited control. The
particular form of delimited control that I will use here is due to
\citet{DanvyF89}.
%
Nevertheless, the secret sauce of all forms of delimited control is
that a delimited control operator makes it possible to pry open
function boundaries as control may transfer out of an arbitrary
evaluation context, leaving behind a hole that can later be filled by
some value supplied externally.
\citeauthor{DanvyF89}'s formulation of delimited control introduces
the following two primitives.
%
\[
\reset{-} : (\UnitType \to R) \to R \qquad\quad
\shift : ((A \to R) \to R) \to A
\]
%
The first primitive $\reset{-}$ (pronounced `reset') is a control
delimiter. Operationally, reset evaluates a given thunk in an empty
evaluation context and returns the final result of that evaluation.
%
The second primitive $\shift$ is a control reifier. An application
$\shift$ reifies and erases the control state up to (but not
including) the nearest enclosing reset. The reified control state
represents the continuation of the invocation of $\shift$ (up to the
innermost reset); it gets passed as a function to the argument of
$\shift$.
Both primitives are defined over some (globally) fixed result type
$R$.
%
By instantiating $R = S \to A \times S$, where $S$ is the type of
state and $A$ is the type of return values, then we can use shift and
reset to simulate mutable state using state-passing in way that is
opaque to the rest of the program.
%
Let us first define operations for accessing and modifying the state
cell.
%
\[ \[
\ba{@{~}l@{\qquad\quad}@{~}r} \ba{@{~}l@{\qquad\quad}@{~}r}
\multirow{2}{*}{ \multirow{2}{*}{
\bl \bl
\getF : \UnitType \to S\\ \getF : \UnitType \to S\\
\getF~\Unit \defas \shift~k.\lambda st. k~st~st
\getF~\Unit \defas \shift\,(\lambda k.\lambda st. k~st~st)
\el} & \el} &
\multirow{2}{*}{ \multirow{2}{*}{
\bl \bl
\putF : S \to \UnitType\\ \putF : S \to \UnitType\\
\putF~st \defas \shift~k.\lambda st'.k~\Unit~st
\putF~st \defas \shift\,(\lambda k.\lambda st'.k~\Unit~st)
\el} \\ & % space hack to avoid the next paragraph from \el} \\ & % space hack to avoid the next paragraph from
% floating into the math environment. % floating into the math environment.
\ea \ea
\] \]
% %
The body of $\getF$ applies $\shift$ to capture the current
continuation, which gets supplied to the anonymous function
$(\lambda k.\lambda st. k~st~st)$. The continuation parameter $k$ has
type $S \to S \to A \times S$. The continuation is applied to two
instances of the current state value $st$. The instance the value
returned to the caller of $\getF$, whilst the second instance is the
state value available during the next invocation of either $\getF$ or
$\putF$. This aligns with the intuition that accessing a state cell
does not modify its contents. The implementation of $\putF$ is
similar, except that the first argument to $k$ is the unit value,
because the caller of $\putF$ expects a unit in return. Also, it
ignores the current state value $st'$ and instead passes the state
argument $st$ onto the activation of the next state operation. Again,
this aligns with the intuition that modifying a state cell destroys
its previous contents.
Using these two operations we can implement a version of $\incrEven$
that takes advantage of delimited control to simulate global state.
%
\[ \[
\bl \bl
\incrEven : \UnitType \to \Bool\\ \incrEven : \UnitType \to \Bool\\
@ -522,17 +588,40 @@ state $S$ we have to transform its type as follows.
\el \el
\] \]
% %
Modulo naming of operations, this version is similar to the version
that uses builtin state. The type signature of the function is even
the same.
%
Before we can apply this function we must first a state initialiser.
%
\[ \[
\bl \bl
\runState : S \to (\UnitType \to A) \to A \times S\\
\runState~st~m \defas \pmb{\langle} \Let\;x \revto f\,\Unit\;\In\;\lambda st. \Record{x;st} \pmb{\rangle}\,st
\runState : (\UnitType \to A) \to S \to A \times S\\
\runState~m~st_0 \defas \reset{\lambda\Unit.\Let\;x \revto m\,\Unit\;\In\;\lambda st. \Record{x;st}}\,st_0
\bl \bl
\el \el
\el \el
\] \]
% %
The function $\runState$ is both the state cell initialiser and runner
of the stateful computation.
The function $\runState$ acts as both the state cell initialiser and
runner of the stateful computation. The first parameter $m$ is a thunk
that may perform stateful operations and the second parameter $st_0$
is the initial value of the state cell. The implementation wraps an
instance of reset around the application of $m$ in order to delimit
the extent of applications of $\shift$ within $m$. It is important to
note that each invocation of $\getF$ and $\putF$ gives rise to a
state-accepting function, thus when $m$ is applied a chain of
state-accepting functions gets constructed lazily. The chain ends in
the state-accepting function returned by the reset instance. The
application of the reset instance to $st_0$ effectively causes
evaluation of each function in this chain to start.
After instantiating $A = \Bool$ and $S = \Int$ we can use the
$\runState$ function to apply the $\incrEven$ function.
%
\[
\runState~\incrEven~4~ \reducesto^+ \Record{\True;5} : \Bool \times \Int
\]
\subsection{Monadic epoch} \subsection{Monadic epoch}
During the late 80s and early 90s monads rose to prominence as a During the late 80s and early 90s monads rose to prominence as a
@ -945,8 +1034,8 @@ operation is another computation tree node.
% %
\[ \[
\bl \bl
\runState : S \to \Free\,(\dec{FreeState}~S)\,A \to A \times S\\
\runState~st~m \defas
\runState : \Free\,(\dec{FreeState}~S)\,A \to S \to A \times S\\
\runState~m~st \defas
\Case\;m\;\{ \Case\;m\;\{
\ba[t]{@{~}l@{~}c@{~}l} \ba[t]{@{~}l@{~}c@{~}l}
\return~x &\mapsto& (x, st);\\ \return~x &\mapsto& (x, st);\\
@ -961,7 +1050,7 @@ operation is another computation tree node.
\] \]
\subsection{Back to direct-style} \subsection{Back to direct-style}
Combining monadic effects~\cite{VazouL16}\dots
\subsubsection{Effect tracking} \subsubsection{Effect tracking}
@ -1427,13 +1516,13 @@ distinct notions of continuations. It is common in the literature to
find the word `continuation' accompanied by a qualifier such as full, find the word `continuation' accompanied by a qualifier such as full,
partial, abortive, escape, undelimited, delimited, composable, or partial, abortive, escape, undelimited, delimited, composable, or
functional (in Chapter~\ref{ch:cps} I will extend this list by three functional (in Chapter~\ref{ch:cps} I will extend this list by three
new ones). Some of these notions of continuations synonyms, whereas
others have distinct meaning. Common to all notions of continuations
is that in essence they represent the control state. However, the
new ones). Some of these notions of continuations are synonymous,
whereas others have distinct meanings. Common to all notions of
continuations is that they represent the control state. However, the
extent and behaviour of continuations differ widely from notion to extent and behaviour of continuations differ widely from notion to
notion. The essential notions of continuations are notion. The essential notions of continuations are
undelimited/delimited and abortive/composable. To tell them apart, we undelimited/delimited and abortive/composable. To tell them apart, we
will classify them by their operational behaviour.
will classify them according to their operational behaviour.
The extent and behaviour of a continuation in programming are The extent and behaviour of a continuation in programming are
determined by its introduction and elimination forms, determined by its introduction and elimination forms,

Loading…
Cancel
Save