mirror of
https://github.com/achlipala/frap.git
synced 2024-12-01 00:26:18 +00:00
Start of embeddings chapter
This commit is contained in:
parent
cf003490a2
commit
477113cf40
2 changed files with 100 additions and 7 deletions
|
@ -14,3 +14,5 @@ Just run `make` here to build everything, including the book `frap.pdf` and the
|
|||
* Chapter 7: `AbstractInterpretation.v`
|
||||
* Chapter 8: `LambdaCalculusAndTypeSoundness.v`
|
||||
* Chapter 9: `TypesAndMutation.v`
|
||||
* Chapter 10: `HoareLogic.v`
|
||||
* Chapter 11: `DeepAndShallowEmbeddings.v`
|
||||
|
|
105
frap_book.tex
105
frap_book.tex
|
@ -16,9 +16,6 @@
|
|||
\numberwithin{section}{chapter}
|
||||
\numberwithin{equation}{chapter}
|
||||
|
||||
% For a single index; for multiple indexes, see the manual
|
||||
% "Instructions for preparation of papers and monographs:
|
||||
% AMS-LaTeX" (instr-l.pdf in the AMS-LaTeX distribution).
|
||||
\makeindex
|
||||
|
||||
\begin{document}
|
||||
|
@ -27,9 +24,6 @@
|
|||
|
||||
\title{Formal Reasoning About Programs}
|
||||
|
||||
% Remove any unused author tags.
|
||||
|
||||
% author one information
|
||||
\author{Adam Chlipala}
|
||||
\address{MIT, Cambridge, MA, USA}
|
||||
\email{adamc@csail.mit.edu}
|
||||
|
@ -451,6 +445,7 @@ Here, unification found the assignment $e = \mathsf{Var}(x)$.
|
|||
\medskip
|
||||
|
||||
\encoding
|
||||
\label{metalanguage}
|
||||
We close the chapter with an important note on terminology.
|
||||
A formula like $P(\size{\mathsf{Plus}(\mathsf{Var}(x), \mathsf{Const}(7))})$ combines several levels of notation.
|
||||
We consider that we are doing our mathematical reasoning in some \emph{metalanguage}\index{metalanguage}, which is often applicable to a wide variety of proof tasks.
|
||||
|
@ -465,7 +460,7 @@ The quoted remark could just as well be in Spanish instead of English, in which
|
|||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\chapter{Semantics via Interpreters}
|
||||
\chapter{\label{interpreters}Semantics via Interpreters}
|
||||
|
||||
That's enough about what programs \emph{look like}.
|
||||
Let's shift our attention to what programs \emph{mean}.
|
||||
|
@ -2907,6 +2902,102 @@ In fact, we can prove that any other state is unstuck, though we won't bother he
|
|||
\end{proof}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\chapter{Deep Embeddings, Shallow Embeddings, and Options in Between}
|
||||
|
||||
So far, in this book, we have followed the typographic conventions of ordinary mathematics and logic, as they would be worked out on whiteboards.
|
||||
In parallel, we have mechanized all of the definitions and proofs in Coq.
|
||||
Often little tidbits of encoding challenge show up in mechanizing the proofs.
|
||||
As formal languages get more complex, it becomes more and more important to choose the right encoding.
|
||||
For instance, in the previous chapter, we repeatedly jumped through hoops to track the local variables of programs, threading variable valuations $v$ throughout everything.
|
||||
Coq already has built into it a respectable notion of variables; can we somehow reuse that mechanism, rather than roll our own new one?
|
||||
This chapter gives a ``yes'' answer, working toward redefining last chapter's Hoare logic in a lighter-weight manner, along the way introducing some key terminology that is used to classify encoding choices.
|
||||
|
||||
Since whiteboard math doesn't usually bother with encoding details, here we must break with our convention of using only standard notation in the book.
|
||||
Instead, we will use notation closer to literal Coq code, and, in fact, more of the technical action than usual is only found in the accompanying Coq source file.
|
||||
|
||||
\section{The Basics}
|
||||
|
||||
Recall some terminology introduced in Section \ref{metalanguage}: every formal proof is carried out in some \emph{metalanguage}\index{metalanguage}, which, in our case, is Coq's logic and programming language called Gallina\index{Gallina}.
|
||||
A syntactic language that we formalize is called an \emph{object language}\index{object language}.
|
||||
Often it is convenient to do reasoning without any particular object language, as in this simple arithmetic function that can be defined directly in Gallina.
|
||||
\newcommand{\mt}[1]{\mathsf{#1}}
|
||||
\begin{eqnarray*}
|
||||
\mt{foo} &=& \lambda(x, y). \; \elet{u}{x + y}{\elet{v}{u \times y}{u + v}}
|
||||
\end{eqnarray*}
|
||||
|
||||
However, it is difficult to prove some important facts about terms encoded directly in the metalanguage.
|
||||
For instance, we can't easily do induction over the syntax of all such terms.
|
||||
To allow that kind of induction, we can define an object language inductively.
|
||||
\begin{eqnarray*}
|
||||
\mt{Const} &:& \mathbb N \to \mt{exp} \\
|
||||
\mt{Var} &:& \mathbb V \to \mt{exp} \\
|
||||
\mt{Plus} &:& \mt{exp} \to \mt{exp} \to \mt{exp} \\
|
||||
\mt{Times} &:& \mt{exp} \to \mt{exp} \to \mt{exp} \\
|
||||
\mt{Let} &:& \mathbb V \to \mt{exp} \to \mt{exp} \to \mt{exp}
|
||||
\end{eqnarray*}
|
||||
|
||||
That last example program, with implicit \emph{free variables}\index{free variables} $x$ and $y$, may now be redefined in the $\mt{exp}$ type.
|
||||
\newcommand{\var}[1]{\mt{Var} \; \textrm{``#1''}}
|
||||
\begin{eqnarray*}
|
||||
\mt{foo'} &=& \mt{Let} \; (\var{u}) \; (\mt{Plus} \; (\var{x}) \; (\var{y})) \; (\mt{Let} \; (\var{v}) \\
|
||||
&& \hspace{.1in} (\mt{Times} \; (\var{u}) \; (\var{y})) \; (\mt{Plus} \; (\var{u}) \; (\var{v})))
|
||||
\end{eqnarray*}
|
||||
|
||||
As in Chapter \ref{interpreters}, we can define a recursive interpreter, mapping $\mt{exp}$ programs and variable valuations to numbers.
|
||||
Using that interpreter, we can prove equivalence of $\mt{foo}$ and $\mt{foo'}$.
|
||||
|
||||
We say that $\mt{foo}$ uses a \emph{shallow embedding}\index{shallow embedding}, because it is coded directly in the metalanguage, with no extra layer of syntax.
|
||||
Conversely, $\mt{foo'}$ uses a \emph{deep embedding}\index{deep embedding}, since it goes via the inductively defined $\mt{exp}$ type.
|
||||
|
||||
These extremes are not our only options.
|
||||
In higher-order logics like Coq's, we may also choose what might be called \emph{mixed embeddings}\index{mixed embedding}, which define syntax-tree types that allow some use of general functions from the metalanguage.
|
||||
Here's an example, as an alternative definition of $\mt{exp}$.
|
||||
\begin{eqnarray*}
|
||||
\mt{Const} &:& \mathbb N \to \mt{exp} \\
|
||||
\mt{Var} &:& \mathbb V \to \mt{exp} \\
|
||||
\mt{Plus} &:& \mt{exp} \to \mt{exp} \to \mt{exp} \\
|
||||
\mt{Times} &:& \mt{exp} \to \mt{exp} \to \mt{exp} \\
|
||||
\mt{Let} &:& \mt{exp} \to (\mathbb N \to \mt{exp}) \to \mt{exp}
|
||||
\end{eqnarray*}
|
||||
|
||||
The one change is in the type of the $\mt{Let}$ constructor, where now no variable name is given, and instead \emph{the body of the ``let'' is represented as a Gallina function from numbers to expressions}.
|
||||
The intent is that the body is called on the number that results from evaluating the first expression.
|
||||
This style is called \emph{higher-order abstract syntax}\index{higher-order abstract syntax}.
|
||||
Though that term is often applied to a more specific instance of the technique, which is not exactly the one applied here, we will not be so picky.
|
||||
|
||||
As an illustration of the technique in action, here's our third encoding of the simple example program.
|
||||
\begin{eqnarray*}
|
||||
\mt{foo''} &=& \mt{Let} \; (\mt{Plus} \; (\var{x}) \; (\var{y})) \; (\lambda u. \\
|
||||
&& \hspace{.1in} \mt{Let} \; (\mt{Times} \; (\mt{Const} \; u) \; (\var{y})) \; (\lambda v. \\
|
||||
&& \hspace{.2in} \mt{Plus} \; (\mt{Const} \; u) \; (\mt{Const} \; v)))
|
||||
\end{eqnarray*}
|
||||
|
||||
With a bit of subtlety, we can define an interpreter for this language, too.
|
||||
\begin{eqnarray*}
|
||||
\denote{\mt{Const} \; n}v &=& n \\
|
||||
\denote{\mt{Var} \; x}v &=& \msel{v}{x} \\
|
||||
\denote{\mt{Plus} \; e_1 \; e_2}v &=& \denote{e_1}v + \denote{e_2}v \\
|
||||
\denote{\mt{Times} \; e_1 \; e_2}v &=& \denote{e_1}v \times \denote{e_2}v \\
|
||||
\denote{\mt{Let} \; e_1 \; e_2}v &=& \denote{e_2(\denote{e_1}v)}v
|
||||
\end{eqnarray*}
|
||||
|
||||
Note how, in the $\mt{Let}$ case, since the body $e_2$ is a function, before evaluating it, we call it on the result of evaluating $e_1$.
|
||||
This language would actually be sufficient even if we removed the $\mt{Var}$ constructor and the $v$ argument of the interpreter.
|
||||
Coq's normal variable binding is enough to let us model interesting programs and prove things about them by induction on syntax.
|
||||
|
||||
It is important here that Coq's induction principles give us useful induction hypotheses, for constructors whose recursive arguments are functions.
|
||||
The second argument of $\mt{Let}$ above is an example.
|
||||
When we do induction on expression syntax to establish $\forall e. \; P(e)$, the case for $\mt{Let} \; e_1 \; e_2$ includes two induction hypotheses.
|
||||
The first one is standard: $P(e_1)$.
|
||||
The second one is more interesting: $\forall n : \mathbb N. \; P(e_2(n))$.
|
||||
That is, the theorem holds on all results of applying body $e_2$ to arguments.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
|
Loading…
Reference in a new issue