mirror of
https://github.com/dhil/phd-dissertation
synced 2026-03-13 11:08:25 +00:00
WIP
This commit is contained in:
75
thesis.bib
75
thesis.bib
@@ -195,6 +195,18 @@
|
|||||||
year = {2001}
|
year = {2001}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inproceedings{PlotkinP02,
|
||||||
|
author = {Gordon D. Plotkin and
|
||||||
|
John Power},
|
||||||
|
title = {Notions of Computation Determine Monads},
|
||||||
|
booktitle = {FoSSaCS},
|
||||||
|
series = {Lecture Notes in Computer Science},
|
||||||
|
volume = {2303},
|
||||||
|
pages = {342--356},
|
||||||
|
publisher = {Springer},
|
||||||
|
year = {2002}
|
||||||
|
}
|
||||||
|
|
||||||
# Other algebraic effects and handlers
|
# Other algebraic effects and handlers
|
||||||
@inproceedings{Lindley14,
|
@inproceedings{Lindley14,
|
||||||
author = {Sam Lindley},
|
author = {Sam Lindley},
|
||||||
@@ -880,7 +892,14 @@
|
|||||||
year = 1971
|
year = 1971
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Monad transformers
|
||||||
|
@phdthesis{Espinosa95,
|
||||||
|
author = {David A. Espinosa},
|
||||||
|
school = {Columbia University},
|
||||||
|
title = {Semantic Lego},
|
||||||
|
year = 1995,
|
||||||
|
address = {New York, USA}
|
||||||
|
}
|
||||||
|
|
||||||
# Hop.js
|
# Hop.js
|
||||||
@inproceedings{SerranoP16,
|
@inproceedings{SerranoP16,
|
||||||
@@ -3338,3 +3357,57 @@
|
|||||||
pages = {299--314},
|
pages = {299--314},
|
||||||
year = {1960}
|
year = {1960}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Effect systems
|
||||||
|
@inproceedings{GiffordL86,
|
||||||
|
author = {David K. Gifford and
|
||||||
|
John M. Lucassen},
|
||||||
|
title = {Integrating Functional and Imperative Programming},
|
||||||
|
booktitle = {{LISP} and Functional Programming},
|
||||||
|
pages = {28--38},
|
||||||
|
publisher = {{ACM}},
|
||||||
|
year = {1986}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inproceedings{LucassenG88,
|
||||||
|
author = {John M. Lucassen and
|
||||||
|
David K. Gifford},
|
||||||
|
title = {Polymorphic Effect Systems},
|
||||||
|
booktitle = {{POPL}},
|
||||||
|
pages = {47--57},
|
||||||
|
publisher = {{ACM} Press},
|
||||||
|
year = {1988}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inproceedings{TalpinJ92,
|
||||||
|
author = {Jean{-}Pierre Talpin and
|
||||||
|
Pierre Jouvelot},
|
||||||
|
title = {The Type and Effect Discipline},
|
||||||
|
booktitle = {{LICS}},
|
||||||
|
pages = {162--173},
|
||||||
|
publisher = {{IEEE} Computer Society},
|
||||||
|
year = {1992}
|
||||||
|
}
|
||||||
|
|
||||||
|
@article{TofteT97,
|
||||||
|
author = {Mads Tofte and
|
||||||
|
Jean{-}Pierre Talpin},
|
||||||
|
title = {Region-based Memory Management},
|
||||||
|
journal = {Inf. Comput.},
|
||||||
|
volume = {132},
|
||||||
|
number = {2},
|
||||||
|
pages = {109--176},
|
||||||
|
year = {1997}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inproceedings{NielsonN99,
|
||||||
|
author = {Flemming Nielson and
|
||||||
|
Hanne Riis Nielson},
|
||||||
|
title = {Type and Effect Systems},
|
||||||
|
booktitle = {Correct System Design},
|
||||||
|
series = {Lecture Notes in Computer Science},
|
||||||
|
volume = {1710},
|
||||||
|
pages = {114--136},
|
||||||
|
publisher = {Springer},
|
||||||
|
year = {1999}
|
||||||
|
}
|
||||||
242
thesis.tex
242
thesis.tex
@@ -335,63 +335,104 @@
|
|||||||
%%
|
%%
|
||||||
\chapter{Introduction}
|
\chapter{Introduction}
|
||||||
\label{ch:introduction}
|
\label{ch:introduction}
|
||||||
Control is an ample ingredient of virtually every programming
|
Control is a pervasive phenomenon in virtually every programming
|
||||||
language. A programming language typically feature a variety of
|
language. A programming language typically features a variety of
|
||||||
control constructs, which let the programmer manipulate the control
|
control constructs, which let the programmer manipulate the control
|
||||||
flow of programs in interesting ways. The most well-known control
|
flow of programs in interesting ways. The most well-known control
|
||||||
construct may well be $\If\;V\;\Then\;M\;\Else\;N$, which
|
construct may well be $\If\;V\;\Then\;M\;\Else\;N$, which
|
||||||
conditionally selects between two possible \emph{continuations} $M$
|
conditionally selects between two possible \emph{continuations} $M$
|
||||||
and $N$ depending on whether the condition $V$ is $\True$ or
|
and $N$ depending on whether the condition $V$ is $\True$ or $\False$.
|
||||||
$\False$. Another familiar control construct is function application
|
|
||||||
$\EC[(\lambda x.M)\,W]$, which evaluates some parameterised
|
|
||||||
continuation $M$ at value argument $W$ to normal form and subsequently
|
|
||||||
continues the current continuation induced by the invocation context
|
|
||||||
$\EC$.
|
|
||||||
%
|
%
|
||||||
At the time of writing the trendiest control construct happen to be
|
The $\If$ construct offers no means for programmatic manipulation of
|
||||||
async/await, which is designed for direct-style asynchronous
|
either continuation.
|
||||||
programming~\cite{SymePL11}. It takes the form
|
%
|
||||||
$\async.\,\EC[\await\;M]$, where $\async$ delimits an asynchronous
|
More intriguing forms of control exist, which enable the programmer to
|
||||||
context $\EC$ in which computations may be interleaved. The $\await$
|
manipulate and reify continuations as first-class data objects. This
|
||||||
primitive may be used to defer execution of the current continuation
|
kind of control is known as \emph{first-class control}.
|
||||||
until the result of the asynchronous computation $M$ is ready. Prior
|
%
|
||||||
to async/await the most fashionable control construct was coroutines,
|
The idea of first-class control is old, it was conceived already
|
||||||
which provide the programmer with a construct for performing non-local
|
during the design of the programming language
|
||||||
transfers of control by suspending the current continuation on
|
Algol~\cite{BackusBGKMPRSVWWW60} (one of the early high-level
|
||||||
demand~\cite{MouraI09}, e.g. in
|
programming languages along with Fortran~\cite{BackusBBGHHNSSS57} and
|
||||||
$\keyw{co_0}.\,\EC_0[\keyw{suspend}];\keyw{co_1}.\,\EC_1[\Unit]$ the
|
Lisp~\cite{McCarthy60}) when \citet{Landin98} sought to model
|
||||||
two coroutines $\keyw{co_0}$ and $\keyw{co_1}$ work in tandem by
|
unrestricted goto-style jumps using an extended
|
||||||
invoking suspend in order to hand over control to the other coroutine;
|
$\lambda$-calculus. Albeit, the most (in)famous first-class control
|
||||||
$\keyw{co_0}$ suspends the current continuation $\EC_0$ and transfers
|
operator \emph{call-with-current-continuation} appeared later when it
|
||||||
control to $\keyw{co_1}$, which resume its continuation $\EC_1$ with
|
was introduced by the designers of the programming language
|
||||||
the unit value $\Unit$. The continuation $\EC_1$ may later suspend in
|
Scheme~\cite{AbelsonHAKBOBPCRFRHSHW85}.
|
||||||
order to transfer control back to $\keyw{co_0}$ such that it can
|
%
|
||||||
resume execution of the continuation
|
The ability to manipulate continuations programmatically is incredibly
|
||||||
$\EC_0$~\cite{AbadiP10}. Coroutines are amongst the oldest ideas of
|
powerful as it enables programmers to perform non-local transfers of
|
||||||
the literature as they have been around since the dawn of
|
control on the
|
||||||
programming~\cite{DahlMN68,DahlDH72,Knuth97,MouraI09}. Nevertheless
|
demand. % and it can be used to codify a wealth of control idioms.
|
||||||
coroutines frequently reappear in the literature in various guises.
|
%
|
||||||
|
\dhil{First-class control provides more intriguing forms of control,
|
||||||
|
which reifies the continuation as a first-class data object.}
|
||||||
|
%
|
||||||
|
\dhil{Control effects gives rise to a programming paradigm known as
|
||||||
|
effectful programming}
|
||||||
|
%
|
||||||
|
\dhil{This dissertation is about the operational foundations for
|
||||||
|
programming and implementing effect handlers, a particularly modular
|
||||||
|
and extensible programming abstraction for effectful programming}
|
||||||
|
|
||||||
The common denominator for the aforementioned control constructs is
|
% Control is an ample ingredient of virtually every programming
|
||||||
that they are all second-class.
|
% language. A programming language typically feature a variety of
|
||||||
|
% control constructs, which let the programmer manipulate the control
|
||||||
% Virtually every programming language is equipped with one or more
|
% flow of programs in interesting ways. The most well-known control
|
||||||
% control flow operators, which enable the programmer to manipulate the
|
% construct may well be $\If\;V\;\Then\;M\;\Else\;N$, which
|
||||||
% flow of control of programs in interesting ways. The most well-known
|
|
||||||
% control operator may well be $\If\;V\;\Then\;M\;\Else\;N$, which
|
|
||||||
% conditionally selects between two possible \emph{continuations} $M$
|
% conditionally selects between two possible \emph{continuations} $M$
|
||||||
% and $N$ depending on whether the condition $V$ is $\True$ or $\False$.
|
% and $N$ depending on whether the condition $V$ is $\True$ or
|
||||||
|
% $\False$. Another familiar control construct is function application
|
||||||
|
% $\EC[(\lambda x.M)\,W]$, which evaluates some parameterised
|
||||||
|
% continuation $M$ at value argument $W$ to normal form and subsequently
|
||||||
|
% continues the current continuation induced by the invocation context
|
||||||
|
% $\EC$.
|
||||||
% %
|
% %
|
||||||
% Another familiar operator is function application\dots
|
% At the time of writing the trendiest control construct happen to be
|
||||||
|
% async/await, which is designed for direct-style asynchronous
|
||||||
|
% programming~\cite{SymePL11}. It takes the form
|
||||||
|
% $\async.\,\EC[\await\;M]$, where $\async$ delimits an asynchronous
|
||||||
|
% context $\EC$ in which computations may be interleaved. The $\await$
|
||||||
|
% primitive may be used to defer execution of the current continuation
|
||||||
|
% until the result of the asynchronous computation $M$ is ready. Prior
|
||||||
|
% to async/await the most fashionable control construct was coroutines,
|
||||||
|
% which provide the programmer with a construct for performing non-local
|
||||||
|
% transfers of control by suspending the current continuation on
|
||||||
|
% demand~\cite{MouraI09}, e.g. in
|
||||||
|
% $\keyw{co_0}.\,\EC_0[\keyw{suspend}];\keyw{co_1}.\,\EC_1[\Unit]$ the
|
||||||
|
% two coroutines $\keyw{co_0}$ and $\keyw{co_1}$ work in tandem by
|
||||||
|
% invoking suspend in order to hand over control to the other coroutine;
|
||||||
|
% $\keyw{co_0}$ suspends the current continuation $\EC_0$ and transfers
|
||||||
|
% control to $\keyw{co_1}$, which resume its continuation $\EC_1$ with
|
||||||
|
% the unit value $\Unit$. The continuation $\EC_1$ may later suspend in
|
||||||
|
% order to transfer control back to $\keyw{co_0}$ such that it can
|
||||||
|
% resume execution of the continuation
|
||||||
|
% $\EC_0$~\cite{AbadiP10}. Coroutines are amongst the oldest ideas of
|
||||||
|
% the literature as they have been around since the dawn of
|
||||||
|
% programming~\cite{DahlMN68,DahlDH72,Knuth97,MouraI09}. Nevertheless
|
||||||
|
% coroutines frequently reappear in the literature in various guises.
|
||||||
|
|
||||||
Evidently, control is a pervasive phenomenon in programming. However,
|
% The common denominator for the aforementioned control constructs is
|
||||||
not every control phenomenon is equal in terms of programmability and
|
% that they are all second-class.
|
||||||
expressiveness.
|
|
||||||
|
|
||||||
\section{This thesis in a nutshell}
|
% % Virtually every programming language is equipped with one or more
|
||||||
In this dissertation I am concerned only with
|
% % control flow operators, which enable the programmer to manipulate the
|
||||||
\citeauthor{PlotkinP09}'s deep handlers, their shallow variation, and
|
% % flow of control of programs in interesting ways. The most well-known
|
||||||
parameterised handlers which are a slight variation of deep handlers.
|
% % control operator may well be $\If\;V\;\Then\;M\;\Else\;N$, which
|
||||||
|
% % conditionally selects between two possible \emph{continuations} $M$
|
||||||
|
% % and $N$ depending on whether the condition $V$ is $\True$ or $\False$.
|
||||||
|
% % %
|
||||||
|
% % Another familiar operator is function application\dots
|
||||||
|
|
||||||
|
% Evidently, control is a pervasive phenomenon in programming. However,
|
||||||
|
% not every control phenomenon is equal in terms of programmability and
|
||||||
|
% expressiveness.
|
||||||
|
|
||||||
|
% % \section{This thesis in a nutshell}
|
||||||
|
% % In this dissertation I am concerned only with
|
||||||
|
% % \citeauthor{PlotkinP09}'s deep handlers, their shallow variation, and
|
||||||
|
% % parameterised handlers which are a slight variation of deep handlers.
|
||||||
|
|
||||||
\section{Why first-class control matters}
|
\section{Why first-class control matters}
|
||||||
From the perspective of programmers first-class control is a valuable
|
From the perspective of programmers first-class control is a valuable
|
||||||
@@ -1280,9 +1321,114 @@ The free monad brings us close to the essence of programming with
|
|||||||
effect handlers.
|
effect handlers.
|
||||||
|
|
||||||
\subsection{Back to direct-style}
|
\subsection{Back to direct-style}
|
||||||
Combining monadic effects~\cite{VazouL16}\dots
|
\dhil{The problem with monads is that they do not
|
||||||
|
compose. Cite~\citet{Espinosa95}, \citet{VazouL16}}
|
||||||
|
%
|
||||||
|
Another problem is that monads break the basic doctrine of modular
|
||||||
|
abstraction, which we should program against an abstract interface,
|
||||||
|
not an implementation. A monad is a concrete implementation.
|
||||||
|
|
||||||
|
\subsubsection{Handling state}
|
||||||
|
\dhil{Cite \citet{PlotkinP01,PlotkinP02,PlotkinP03,PlotkinP09,PlotkinP13}.}
|
||||||
|
\[
|
||||||
|
\ba{@{~}l@{~}r}
|
||||||
|
\Do\;\ell^{A \opto B}~M^A : B & \Handle\;M^A\;\With\;H^{A \Harrow B} : B \smallskip\\
|
||||||
|
\multicolumn{2}{c}{H^{A \Harrow B} ::= \{\Return\;x \mapsto M\} \mid \{\OpCase{\ell}{p}{k} \mapsto M\} \uplus H}
|
||||||
|
\ea
|
||||||
|
\]
|
||||||
|
The operation symbols are declared in a signature
|
||||||
|
$\ell : A \opto B \in \Sigma$.
|
||||||
|
%
|
||||||
|
\[
|
||||||
|
\ba{@{~}l@{\qquad\quad}@{~}r}
|
||||||
|
\multicolumn{2}{l}{\Sigma \defas \{\Get : \UnitType \opto S;\Put : S \opto \UnitType\}} \smallskip\\
|
||||||
|
\multirow{2}{*}{
|
||||||
|
\bl
|
||||||
|
\getF : \UnitType \to S\\
|
||||||
|
\getF~\Unit \defas \Do\;\Get\,\Unit
|
||||||
|
\el} &
|
||||||
|
\multirow{2}{*}{
|
||||||
|
\bl
|
||||||
|
\putF : S \to \UnitType\\
|
||||||
|
\putF~st \defas \Do\;\Put~st
|
||||||
|
\el} \\ & % space hack to avoid the next paragraph from
|
||||||
|
% floating into the math environment.
|
||||||
|
\ea
|
||||||
|
\]
|
||||||
|
%
|
||||||
|
As with the free monad, we are completely free to pick whatever
|
||||||
|
interpretation of state we desire. However, if we want an
|
||||||
|
interpretation that is compatible with the usual equations for state,
|
||||||
|
then we can simply use the state-passing technique again.
|
||||||
|
%
|
||||||
|
\[
|
||||||
|
\bl
|
||||||
|
\runState : (\UnitType \to A) \to S \to A \times S\\
|
||||||
|
\runState~m~st_0 \defas
|
||||||
|
\bl
|
||||||
|
\Let\;f \revto \Handle\;m\,\Unit\;\With\\~\{
|
||||||
|
\ba[t]{@{}l@{~}c@{~}l}
|
||||||
|
\Return\;x &\mapsto& \lambda st.\Record{x;st};\\
|
||||||
|
\OpCase{\Get}{\Unit}{k} &\mapsto& \lambda st.k~st~st;\\
|
||||||
|
\OpCase{\Put}{st'}{k} &\mapsto& \lambda st.k~\Unit~st'\}
|
||||||
|
\ea\\
|
||||||
|
\In\;f~st_0
|
||||||
|
\el
|
||||||
|
\el
|
||||||
|
\]
|
||||||
|
%
|
||||||
|
Note the similarity with the implementation of the interpreter for the
|
||||||
|
free state monad. Save for the syntactic differences, the main
|
||||||
|
difference between this implementation and the free state monad
|
||||||
|
interpreter is that here the continuation $k$ implicitly reinstalls
|
||||||
|
the handler, whereas in the free state monad interpreter we explicitly
|
||||||
|
reinstalled the handler via a recursive application.
|
||||||
|
%
|
||||||
|
By fixing $S = \Int$ we can use the above effect handler to run the
|
||||||
|
delimited control variant of $\incrEven$.
|
||||||
|
%
|
||||||
|
\[
|
||||||
|
\runState~\incrEven~4 \reducesto^+ \Record{\True;5} : \Bool \times \Int
|
||||||
|
\]
|
||||||
|
|
||||||
\subsubsection{Effect tracking}
|
\subsubsection{Effect tracking}
|
||||||
|
\dhil{Cite \citet{GiffordL86}, \citet{LucassenG88}, \citet{TalpinJ92},
|
||||||
|
\citet{TofteT97}, \citet{NielsonN99}.}
|
||||||
|
|
||||||
|
A benefit of using monads for effectful programming is that we get
|
||||||
|
effect tracking `for free' (some might object to this statement and
|
||||||
|
claim we paid for it by having to program in monadic style). Effect
|
||||||
|
tracking is a useful tool for making programming with effects less
|
||||||
|
prone to error in much the same way a static type system is useful
|
||||||
|
detecting a wide range of potential runtime errors at compile
|
||||||
|
time.
|
||||||
|
|
||||||
|
The principal idea of an effect system is to annotate computation
|
||||||
|
types with the collection of effects that their inhabitants are
|
||||||
|
allowed to perform, e.g. the type $A \to B \eff E$ denotes a function
|
||||||
|
that accepts a value of type $A$ as input and ultimately returns a
|
||||||
|
value of type $B$. As it computes the $B$ value it is allowed to use
|
||||||
|
the operations given by the effect signature $E$.
|
||||||
|
|
||||||
|
This typing discipline fits nicely with the effect handlers-style of
|
||||||
|
programming. The $\Do$ construct provides a mechanism for injecting an
|
||||||
|
operation into the effect signature, whilst the $\Handle$ construct
|
||||||
|
provides a way to eliminate an effect operation from the signature.
|
||||||
|
%
|
||||||
|
If we instantiate $A = \UnitType$, $B = \Bool$, and $E = \Sigma$, then
|
||||||
|
we obtain a type-and-effect signature for the control effects version
|
||||||
|
of $\incrEven$.
|
||||||
|
%
|
||||||
|
\[
|
||||||
|
\incrEven : \UnitType \to \Bool \eff \{\Get:\UnitType \opto \Int;\Put:\Int \opto \UnitType\}
|
||||||
|
\]
|
||||||
|
%
|
||||||
|
Now, the signature of $\incrEven$ communicates precisely what it
|
||||||
|
expects from the ambient context. It is clear that we must run this
|
||||||
|
function under a handler that interprets at least $\Get$ and $\Put$.
|
||||||
|
|
||||||
|
\dhil{Mention the importance of polymorphism in effect tracking}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\section{Contributions}
|
\section{Contributions}
|
||||||
|
|||||||
Reference in New Issue
Block a user