Final project files
This commit is contained in:
parent
43f1499c72
commit
e5c0950bef
|
@ -0,0 +1 @@
|
||||||
|
cbpv.pdf filter=lfs diff=lfs merge=lfs -text
|
|
@ -1 +1,3 @@
|
||||||
build/
|
build/
|
||||||
|
latex.out/
|
||||||
|
.vscode/
|
|
@ -0,0 +1,47 @@
|
||||||
|
MAIN := cbpv
|
||||||
|
RULES := rules
|
||||||
|
OLD := old
|
||||||
|
DIFF := diff
|
||||||
|
|
||||||
|
LATEX_FLAGS := -jobname=$(MAIN) -shell-escape
|
||||||
|
LATEXRUN := ./latexrun -Wall --latex-cmd lualatex --latex-args "$(LATEX_FLAGS)"
|
||||||
|
LATEXDIFF := latexdiff
|
||||||
|
BIBTEX := bibtex
|
||||||
|
|
||||||
|
OTT = ott
|
||||||
|
OTTFILES = $(MAIN).ott
|
||||||
|
OTT_FLAGS = -tex_wrap false -tex_show_meta false -merge true $(OTTFILES)
|
||||||
|
|
||||||
|
MAKEDEPS := Makefile
|
||||||
|
LATEXDEPS := $(MAIN).bib
|
||||||
|
MOREDEPS := listproc.sty ottalt.sty
|
||||||
|
GENERATED := $(RULES).tex $(MAIN).tex
|
||||||
|
|
||||||
|
all: $(MAIN).pdf
|
||||||
|
|
||||||
|
$(RULES).tex: $(OTTFILES)
|
||||||
|
$(OTT) -o $(RULES).tex $(OTT_FLAGS)
|
||||||
|
|
||||||
|
$(MAIN).tex: $(RULES).tex $(MAIN).mng
|
||||||
|
$(OTT) -tex_filter $(MAIN).mng $(MAIN).tex $(OTT_FLAGS)
|
||||||
|
|
||||||
|
.PHONY: FORCE
|
||||||
|
$(MAIN).pdf: $(MAIN).tex $(LATEXDEPS)
|
||||||
|
$(LATEXRUN) $(MAIN).tex
|
||||||
|
|
||||||
|
$(DIFF).pdf: $(RULES).tex $(MAIN).mng
|
||||||
|
$(LATEXDIFF) $(OLD).mng $(MAIN).mng > $(DIFF).mng
|
||||||
|
$(OTT) -tex_filter $(DIFF).mng $(DIFF).tex $(OTT_FLAGS)
|
||||||
|
$(LATEXRUN) -o $(DIFF).pdf $(DIFF).tex
|
||||||
|
rm $(DIFF).mng $(DIFF).tex
|
||||||
|
|
||||||
|
.PHONY: zip
|
||||||
|
zip: $(MAIN).pdf
|
||||||
|
cp latex.out/$(MAIN).bbl $(MAIN).bbl
|
||||||
|
zip -o submit.zip $(MAIN).bbl $(LATEXDEPS) $(MOREDEPS) $(GENERATED)
|
||||||
|
rm $(MAIN).bbl
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(LATEXRUN) --clean-all
|
||||||
|
rm -f $(GENERATED)
|
|
@ -13,3 +13,4 @@ Exercise numbers refer to TAPL.
|
||||||
| 5 | 15.3.6, 16.1.3, 16.2.5, 16.2.6, 16.3.2 | 24 Feburary |
|
| 5 | 15.3.6, 16.1.3, 16.2.5, 16.2.6, 16.3.2 | 24 Feburary |
|
||||||
| 6 | Barendregt's or Gallier's normalization proof | 5 March |
|
| 6 | Barendregt's or Gallier's normalization proof | 5 March |
|
||||||
| 7 | 22.3.9, 22.3.10, 22.4.6, 22.5.5 | 17 March |
|
| 7 | 22.3.9, 22.3.10, 22.4.6, 22.5.5 | 17 March |
|
||||||
|
| 8 | 26.3.5, 26.4.11, 28.2.3, 28.7.1 | 26 March |
|
|
@ -0,0 +1,650 @@
|
||||||
|
\documentclass{article}
|
||||||
|
|
||||||
|
\usepackage[supertabular]{ottalt}
|
||||||
|
\let\newlist\relax
|
||||||
|
\let\renewlist\relax
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage{mlmodern}
|
||||||
|
\usepackage[margin=1in]{geometry}
|
||||||
|
\usepackage{enumitem,float,booktabs,xspace,doi}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage[capitalize,nameinlink]{cleveref}
|
||||||
|
\usepackage{mathpartir,mathtools,stmaryrd}
|
||||||
|
|
||||||
|
\setlist{nosep}
|
||||||
|
\hypersetup{
|
||||||
|
colorlinks=true,
|
||||||
|
urlcolor=blue,
|
||||||
|
linkcolor=magenta,
|
||||||
|
citecolor=teal
|
||||||
|
}
|
||||||
|
\urlstyle{tt}
|
||||||
|
|
||||||
|
\newtheorem{theorem}{Theorem}
|
||||||
|
\newtheorem{lemma}[theorem]{Lemma}
|
||||||
|
\newtheorem{corollary}[theorem]{Corollary}
|
||||||
|
\theoremstyle{definition}
|
||||||
|
\newtheorem{definition}{Definition}
|
||||||
|
|
||||||
|
\newcommand{\ie}{\textit{i.e.}\@\xspace}
|
||||||
|
\newcommand{\ala}{\textit{\`a la}\@\xspace}
|
||||||
|
\newcommand{\apriori}{\textit{a priori}\@\xspace}
|
||||||
|
\newcommand{\aposteriori}{\textit{a posteriori}\@\xspace}
|
||||||
|
|
||||||
|
\title{Strong Normalization for \\ Simply Typed Call-by-Push-Value}
|
||||||
|
\author{Jonathan Chan}
|
||||||
|
\date{}
|
||||||
|
|
||||||
|
\inputott{rules}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\section{Introduction}
|
||||||
|
|
||||||
|
The goal of this project is to mechanize a proof of strong normalization for call-by-push-value (CBPV).
|
||||||
|
It follows work by Forster, Sch\"afer, Spies, and Stark (TODO: cite) on mechanizing the metatheory of CBPV in Rocq,
|
||||||
|
but instead adapts the proof technique from POPLMark Reloaded (TODO: cite).
|
||||||
|
|
||||||
|
Both proofs, and mine, follow the same sequence of steps:
|
||||||
|
we define a logical relation that semantically interpret types as sets of terms,
|
||||||
|
show that these sets are backward closed by reduction and that they contain only strongly normalizing terms,
|
||||||
|
prove a fundamental soundness theorem that places well typed terms in the semantic interpretations of their types,
|
||||||
|
and conclude that well typed terms must be strongly normalizing.
|
||||||
|
The difference lies in \emph{how strong normalization} (and reduction) is defined.
|
||||||
|
The Rocq mechanization uses a traditional definition of strong normalization as an accessibility relation,
|
||||||
|
while POPLMark Reloaded and this project use an inductive characterization of strong normalization,
|
||||||
|
then prove it sound with respect to the traditional definition.
|
||||||
|
|
||||||
|
In contrast to both prior works, which use Rocq, Agda, or Beluga,
|
||||||
|
this project is mechanized in Lean.
|
||||||
|
A secondary purpose of this project is to assess the capabilities of Lean for PL metatheory,
|
||||||
|
especially when making heavy use of mutually defined inductive types.
|
||||||
|
I have implemented a mutual induction tactic for Lean (TODO: link),
|
||||||
|
and the mutual values and computations of CBPV,
|
||||||
|
combined with the even more complex mutual inductives from POPLMark Reloaded,
|
||||||
|
make it an attractive test case to test the tactic's robustness.
|
||||||
|
|
||||||
|
This report is divided in roughly the same shape as the proof development.
|
||||||
|
\Cref{sec:syntax} introduces the syntax and the typing rules for CBPV (\texttt{Syntax.lean}, \texttt{Typing.lean}).
|
||||||
|
Then the inductive characterization of strong normalization is defined in \cref{sec:sn-ind} (\texttt{NormalInd.lean}),
|
||||||
|
followed by the logical relation in \cref{sec:lr} (\texttt{OpenSemantics.lean}).
|
||||||
|
The central theorem of strong normalization is proven in \cref{sec:soundness}
|
||||||
|
as a corollary of the fundamental theorem for the logical relation (\texttt{Soundness.lean}, \texttt{Normalization.lean}).
|
||||||
|
To ensure that the inductive characterization is correct,
|
||||||
|
\cref{sec:sn-acc} shows that it implies the traditional definition of strong normalization (\texttt{NormalAcc.lean}).
|
||||||
|
This latter definition and proof depends on small-step reduction on open terms,
|
||||||
|
whose properties are omitted here (\texttt{Reduction.lean}).
|
||||||
|
In general, I gloss over details about substitution and reduction,
|
||||||
|
since I'm interested in presenting the structure of the strong normalization proof
|
||||||
|
and not the minutiae of syntax and binding.
|
||||||
|
Finally, I discuss the merits of this proof technique
|
||||||
|
and the challenges posed by using Lean in \cref{sec:discussion}.
|
||||||
|
|
||||||
|
\section{Syntax and Typing} \label{sec:syntax}
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
[[A]] &\Coloneqq [[Unit]] \mid [[A1 + A2]] \mid [[U B]] & \textit{value types} \\
|
||||||
|
[[B]] &\Coloneqq [[A → B]] \mid [[F A]] & \textit{computation types} \\
|
||||||
|
[[v]], [[w]] &\Coloneqq [[x]] \mid [[unit]] \mid [[inl v]] \mid [[inr v]] \mid [[thunk m]] & \textit{values} \\
|
||||||
|
[[m]], [[n]] &\Coloneqq [[force v]] \mid [[λx. m]] \mid [[m v]] \mid [[ret v]] & \textit{computations} \\
|
||||||
|
& \mid [[let x m n]] \\
|
||||||
|
& \mid [[case v | y.m | z.n]] \\
|
||||||
|
[[G]] &\Coloneqq [[•]] \mid [[G, x : A]] & \textit{typing contexts} \\
|
||||||
|
[[s]] &\Coloneqq [[•]] \mid [[s, x ↦ v]] & \textit{simultaneous substitutions}
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
The grammar of the CBPV for this project is given above.
|
||||||
|
Terms and their types are divided between \emph{values} and \emph{computations}.
|
||||||
|
Values are variables, unit, injections into a sum type, or a thunked computation,
|
||||||
|
while computations are forcing thunks,
|
||||||
|
functions, applications, returning values, binding returned values,
|
||||||
|
and case analysis on sums.
|
||||||
|
There are only value variables and no computation variables,
|
||||||
|
since they represent terms that require no more work to be done on them ready to be substituted in,
|
||||||
|
and typing contexts similarly only contain value types.
|
||||||
|
I use $t$ to refer to terms that may be either values or computations.
|
||||||
|
|
||||||
|
Although the syntax is presented nominally,
|
||||||
|
the mechanization uses an unscoped de Bruijn indexed representation of variables,
|
||||||
|
along with simultaneous substitutions $[[s]]$ mapping variables to values,
|
||||||
|
with $[[•]]$ as the identity substitution.
|
||||||
|
Applying a substitution is represented as $[[v{s}]]$ and $[[m{s}]]$,
|
||||||
|
and implemented in terms of renamings,
|
||||||
|
which are mappings from variables to other variables.
|
||||||
|
|
||||||
|
This is not the usual complete CBPV language,
|
||||||
|
since it's missing both value tuples and computation tuples.
|
||||||
|
I exclude them because they are syntactically not much more interesting than returns,
|
||||||
|
whose eliminator is shaped like pattern matching on a singleton value tuple,
|
||||||
|
and than thunks,
|
||||||
|
whose eliminator is shaped like projection on a singleton computation tuple.
|
||||||
|
In contrast, I do include sums, which represent the only way a computation can branch.
|
||||||
|
|
||||||
|
The typing rules below are standard for the values and computations included.
|
||||||
|
The judgements for values and computations are defined mutually,
|
||||||
|
just as are the types and the terms.
|
||||||
|
|
||||||
|
\drules[T]{$[[G ⊢ v : A]]$}{value typing}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[T]{$[[G ⊢ m : B]]$}{computation typing}{Force,Lam,App,Ret,Let,Case}
|
||||||
|
|
||||||
|
\section{Strong Normalization as an Inductive Definition} \label{sec:sn-ind}
|
||||||
|
|
||||||
|
The idea behind the inductive characterization of strong normalization
|
||||||
|
is to describe case by case when a term is strongly normal,
|
||||||
|
rather than showing \aposteriori which terms are strongly normal.
|
||||||
|
This is done in conjunction with defining strongly neutral terms,
|
||||||
|
which are blocked from $\beta$-reduction,
|
||||||
|
and strong head reduction,
|
||||||
|
which expands the set from normal forms
|
||||||
|
to terms which must reduce to normal forms.
|
||||||
|
|
||||||
|
The general recipe for defining these for CBPV is as follows:
|
||||||
|
\begin{itemize}[rightmargin=\leftmargin]
|
||||||
|
\item The only strongly neutral values are variables.
|
||||||
|
\item Strongly neutral computations are eliminators
|
||||||
|
whose head positions are strongly neutral,
|
||||||
|
while all other subterms are strongly normal.
|
||||||
|
\item Strongly normal values are constructors
|
||||||
|
whose subterms are strongly normal,
|
||||||
|
or strongly neutral values, \ie variables.
|
||||||
|
\item Strongly normal computations are constructors
|
||||||
|
whose subterms are strongly normal,
|
||||||
|
or strongly neutral computations,
|
||||||
|
or computations which reduce to strongly normal computations
|
||||||
|
(backward closure).
|
||||||
|
\item Strong head reduction consists of $\beta$ reductions
|
||||||
|
for all eliminators around the corresponding constructors,
|
||||||
|
and congruent reductions in head positions.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Additionally, strong reduction requires premises asserting that
|
||||||
|
the subterms that may ``disappear'' after reduction be strongly normal
|
||||||
|
so that backward closure actually closes over strongly normal terms.
|
||||||
|
These subterms are the values that get substituted into a computation,
|
||||||
|
which may disappear if the computation never actually uses the binding,
|
||||||
|
as well as computation branches not taken.
|
||||||
|
|
||||||
|
Because we're dealing with CBPV, values have no $\beta$ reductions,
|
||||||
|
so there's no need for head reduction of values as there are no heads.
|
||||||
|
Furthermore, there is only one strongly neutral value,
|
||||||
|
so we inline the definition as a variable where needed,
|
||||||
|
but also write it as $[[v ∈ SNe]]$ for symmetry as appropriate.
|
||||||
|
Otherwise, the remaining four judgements are defined mutually below.
|
||||||
|
|
||||||
|
\drules[SNe]{$[[m ∈ SNe]]$}{strongly neutral computations}{Force,App,Let,Case}
|
||||||
|
\drules[SN]{$[[v ∈ SN]]$}{strongly normal values}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[SN]{$[[m ∈ SN]]$}{strongly normal computations}{Lam,Ret,SNe,Red}
|
||||||
|
\drules[SR]{$[[m ⤳ n]]$}{strong head reduction}{Thunk,Lam,Ret,Inl,Inr,App,Let}
|
||||||
|
\drules[SRs]{$[[m ⤳* n]]$}{reflexive, transitive closure of head reduction}{Refl,Trans}
|
||||||
|
|
||||||
|
We also need the reflexive, transitive closure of head reduction,
|
||||||
|
defined as a separate inductive above.
|
||||||
|
Now we show a few simple lemmas about it,
|
||||||
|
along with an inversion lemma for forcing
|
||||||
|
(other inversion lemmas hold, but this is the only one we need).
|
||||||
|
I present them below as judgement pseudorules
|
||||||
|
using a dashed line to indicate that they are admissible rules.
|
||||||
|
These are all proven either by construction
|
||||||
|
or by induction on the first premise.
|
||||||
|
|
||||||
|
\begin{mathpar}
|
||||||
|
\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drule[]{SRs-Once}
|
||||||
|
\drule[]{SRs-TransPP}
|
||||||
|
\drule[]{SRs-App}
|
||||||
|
\drule[]{SRs-Let}
|
||||||
|
\drule[]{SN-Reds}
|
||||||
|
\drule[]{SN-Force-inv}
|
||||||
|
\end{mathpar}
|
||||||
|
|
||||||
|
The most important property of strongly normal terms that we need is antirenaming,
|
||||||
|
which states that undoing a renaming does not change the term's
|
||||||
|
normalization or reduction behaviour.
|
||||||
|
A crucial property that follows is extensionality of applications,
|
||||||
|
which is an inversion lemma specifically when the application argument is a variable.
|
||||||
|
|
||||||
|
\begin{lemma}[Antirenaming] \label{thm:antisubst}
|
||||||
|
Let $[[s]]$ be a renaming,
|
||||||
|
\ie a substitution mapping variables to variables.
|
||||||
|
Then the following hold:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $[[m{s} ∈ SNe]]$ then $[[m ∈ SNe]]$.
|
||||||
|
\item If $[[v{s} ∈ SN]]$ then $[[v ∈ SN]]$.
|
||||||
|
\item If $[[m{s} ∈ SN]]$ then $[[m ∈ SN]]$.
|
||||||
|
\item If $[[m{s} ⤳ n]]$ then there exists some $[[n']]$
|
||||||
|
such that $[[n]] = [[n'{s}]]$ and $[[m ⤳ n']]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the four derivations of
|
||||||
|
$[[m{s} ∈ SNe]]$, $[[v{s} ∈ SN]]$, $[[m{s} ∈ SN]]$, and $[[m{s} ⤳ n]]$.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{corollary}[Extensionality] \label{cor:ext}
|
||||||
|
If $[[m x ∈ SN]]$ then $[[m ∈ SN]]$.
|
||||||
|
\end{corollary}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of strongly normal values.
|
||||||
|
The possible cases are \rref*{SN-SNe,SN-Red}.
|
||||||
|
Destructing the premise of the former gives $[[m ∈ SNe]]$,
|
||||||
|
and we conclude using \rref{SN-SNe} again.
|
||||||
|
In the latter case, we have $[[m x ⤳ n]]$ and $[[n ∈ SN]]$;
|
||||||
|
destructing on the reduction yields the possible cases
|
||||||
|
\rref{SR-Lam,SR-App}.
|
||||||
|
In the first case, we have $[[m{x ↦ v} ∈ SN]]$,
|
||||||
|
so the goal holds by \nameref{thm:antisubst}.
|
||||||
|
In the second case, we have $[[m ⤳ n]]$ and $[[n x ∈ SN]]$,
|
||||||
|
so by the induction hypothesis, we have $[[n ∈ SN]]$,
|
||||||
|
and we conclude using \rref{SN-Red}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\section{Logical Relation on Open Terms} \label{sec:lr}
|
||||||
|
|
||||||
|
The next step is to define a logical relation that semantically interprets types
|
||||||
|
as sets of open terms.
|
||||||
|
The key property we need from these sets is that they contain only strongly normal terms.
|
||||||
|
Because we are working with open terms to prove normalization
|
||||||
|
and not just termination of evaluation of closed terms,
|
||||||
|
we need to consider variables and strongly neutral terms.
|
||||||
|
Having no other information about them other than their strong neutrality,
|
||||||
|
we require that the interpretation sets always contain all strongly neutral terms.
|
||||||
|
|
||||||
|
The logical relation on simple types can be defined by induction on the structure of the type.
|
||||||
|
However, I want to maximize the amount of mutual inductives used in this project,
|
||||||
|
so we instead define the logical relation as an inductive binary relation
|
||||||
|
between the type and the set of terms of its interpretation,
|
||||||
|
denoted as $[[⟦A⟧ ↘ P]]$ and $[[⟦B⟧ ↘ P]]$ below.
|
||||||
|
I use set builder notation to define the sets and set membership,
|
||||||
|
but they are implemented in the mechanization as functions
|
||||||
|
that take terms and return propositions and as function applications.
|
||||||
|
Here, the conjunctions ($\wedge$), disjunctions ($\vee$), equalities ($=$), implications ($\Rightarrow$),
|
||||||
|
and universal ($\forall$) and existential ($\exists$) quantifiers
|
||||||
|
are part of the metatheory, not part of the object language.
|
||||||
|
|
||||||
|
\drules[LR]{$[[⟦A⟧ ↘ P]]$}{semantic interpretation of value types}{Unit,U,Sum}
|
||||||
|
\drules[LR]{$[[⟦B⟧ ↘ P]]$}{semantic interpretation of computation types}{F,Arr}
|
||||||
|
|
||||||
|
The terms in the interpretation of a type can be characterized in two different ways:
|
||||||
|
by what constructor of that type they reduce to,
|
||||||
|
or by how they act when eliminated by an eliminator for that type.
|
||||||
|
For the former, we need to explicitly include the possibility of the term being strongly neutral.
|
||||||
|
I chose the following characterizations because they seemed the simplest to me,
|
||||||
|
but the alternate choices likely work as well.
|
||||||
|
|
||||||
|
\begin{itemize}[noitemsep,rightmargin=\leftmargin]
|
||||||
|
\item Values in the interpretation of the unit type
|
||||||
|
are either variables or the unit value.
|
||||||
|
\item Values are in the interpretation of the $[[U B]]$ type
|
||||||
|
if they can be forced to computations in the interpretation of the $[[B]]$ type.
|
||||||
|
\item Values in the interpretation of the sum type $[[A1 + A2]]$ are either variables,
|
||||||
|
left injections whose values are in the interpretation of $[[A1]]$,
|
||||||
|
or right injections whose values are in that of $[[A2]]$.
|
||||||
|
\item Computations in the interpretation of the $[[F A]]$ type
|
||||||
|
reduce to either a neutral computation
|
||||||
|
or a return whose value is in the interpretation of $[[A]]$.
|
||||||
|
\item Computations are in the interpretation of the function type $[[A → B]]$
|
||||||
|
if applying them to values in the interpretation of $[[A]]$
|
||||||
|
yields computations in the interpretation of $[[B]]$.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
By this description, it sounds like the logical relation can be presented
|
||||||
|
directly as a relation between a type and a term;
|
||||||
|
this presentation is given in \cref{fig:lr-alt}.
|
||||||
|
Unfortunately, this is not well defined,
|
||||||
|
since the logical relation appears in a negative position
|
||||||
|
(to the left of an implication) in the premise of \rref{LRPP-Arr}.
|
||||||
|
The alternate presentation can be interpreted as a function
|
||||||
|
match on the term and the type and returning the conjunction of its premises,
|
||||||
|
but I wanted to use a mutually defined inductive definition.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\fbox{$[[v ∈ ⟦A⟧]]$} \quad \fbox{$[[m ∈ ⟦B⟧]]$} \hfill \textit{} \\
|
||||||
|
\begin{mathpar}
|
||||||
|
\drule[]{LRPP-Unit-var}
|
||||||
|
\drule[]{LRPP-Unit-unit}
|
||||||
|
\drule[]{LRPP-Sum-var}
|
||||||
|
\drule[]{LRPP-Sum-inl}
|
||||||
|
\drule[]{LRPP-Sum-inr}
|
||||||
|
\drule[]{LRPP-Force}
|
||||||
|
\drule[]{LRPP-F-var}
|
||||||
|
\drule[]{LRPP-F-ret}
|
||||||
|
\drule[]{LRPP-Arr}
|
||||||
|
\end{mathpar}
|
||||||
|
\caption{Alternate presentation of the logical relation}
|
||||||
|
\label{fig:lr-alt}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Using the inductive presentation of the logical relation,
|
||||||
|
there are three easy properties to show:
|
||||||
|
interpretability, which states that all types have an interpretation;
|
||||||
|
determinism, which states that the interpretation indeed behaves like a function
|
||||||
|
from types to sets of terms;
|
||||||
|
and backward closure, which states that the interpretations of computation types
|
||||||
|
are backward closed under multi-step head reduction.
|
||||||
|
The last property is why \rref{LRPP-F-var} needs to include
|
||||||
|
computations that \emph{reduce to} strongly neutral terms or returns,
|
||||||
|
not merely ones that are such terms.
|
||||||
|
|
||||||
|
\begin{lemma}[Interpretability] \label{lem:interp} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Given $[[A]]$, there exists $[[P]]$ such that $[[⟦A⟧ ↘ P]]$.
|
||||||
|
\item Given $[[B]]$, there exists $[[P]]$ such that $[[⟦B⟧ ↘ P]]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the types $[[A]]$ and $[[B]]$.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Determinism] \label{lem:det} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $[[⟦A⟧ ↘ P]]$ and $[[⟦A⟧ ↘ Q]]$ then $[[P]] = [[Q]]$.
|
||||||
|
\item If $[[⟦B⟧ ↘ P]]$ and $[[⟦B⟧ ↘ Q]]$ then $[[P]] = [[Q]]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the first derivations of the logical relation,
|
||||||
|
then by cases on the second derivations.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Backward closure] \label{lem:closure}
|
||||||
|
Given $[[⟦B⟧ ↘ P]]$ and $[[m ⤳* n]]$,
|
||||||
|
if $[[n ∈ P]]$ then $[[m ∈ P]]$.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of the logical relation.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
The final key property is adequacy,
|
||||||
|
which states that the interpretations of types
|
||||||
|
must contain all strongly neutral terms
|
||||||
|
and must contain only strongly normal terms.
|
||||||
|
Such sets are said to be \emph{reducibility candidates}.
|
||||||
|
|
||||||
|
\begin{definition}[Reducibility candidates]
|
||||||
|
A reducibility candidate is a set of terms $[[P]]$ where,
|
||||||
|
given a term $[[t]]$,
|
||||||
|
if $[[t ∈ SNe]]$ then $[[t ∈ P]]$, and
|
||||||
|
if $[[t ∈ P]]$ then $[[t ∈ SN]]$.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
\begin{lemma}[Adequacy] \label{lem:adequacy} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $[[⟦A⟧ ↘ P]]$ then $[[P]]$ is a reducibility candidate.
|
||||||
|
\item If $[[⟦B⟧ ↘ P]]$ then $[[P]]$ is a reducibility candidate.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the derivations of the logical relation.
|
||||||
|
\Rref{SN-Force-inv} is used in the \rref*{S-U} case,
|
||||||
|
while \rref{SN-Reds} is used in the \rref{S-F} case.
|
||||||
|
In the \rref*{S-Arr} case on $[[A → B]]$,
|
||||||
|
where $[[⟦A⟧ ↘ P]]$ and $[[⟦B⟧ ↘ Q]]$,
|
||||||
|
to show the second part of its interpretation being a reducibility candidate,
|
||||||
|
we are given $[[m]]$ such that for every $[[v ∈ P]]$, $[[m v ∈ Q]]$,
|
||||||
|
and the goal is to show that $[[m ∈ SN]]$.
|
||||||
|
By the induction hypotheses, picking an arbitrary variable $[[x]]$,
|
||||||
|
we have that $[[x ∈ P]]$ (since it is neutral) and that $[[m x ∈ SN]]$.
|
||||||
|
Then the goal holds by \nameref{cor:ext}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\section{Semantic Typing and the Fundamental Theorem} \label{sec:soundness}
|
||||||
|
|
||||||
|
Now that we know that the interpretations contain only strongly normal terms,
|
||||||
|
our goal is to show that well typed terms inhabit the interpretations of their types.
|
||||||
|
We first define what it means for a substitution to be
|
||||||
|
semantically well formed with respect to a context.
|
||||||
|
|
||||||
|
\begin{definition}[Semantic well-formedness of substitutions]
|
||||||
|
A substitution $[[s]]$ is well formed with respect to a context $[[G]]$,
|
||||||
|
written $[[G ⊧ s]]$, if for every $[[x : A ∈ G]]$ and $[[⟦A⟧ ↘ P]]$,
|
||||||
|
we have $[[x{s} ∈ P]]$.
|
||||||
|
In short, the substitution maps variables in the context
|
||||||
|
to values in the interpretations of their types.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
These judgements can be built up inductively,
|
||||||
|
as demonstrated by the below admissible rules,
|
||||||
|
which are proven by cases.
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[S]{$[[G ⊧ s]]$}{admissible semantic substitution well-formedness}{Nil,Cons}
|
||||||
|
}
|
||||||
|
|
||||||
|
Then we can define semantic typing in terms of the logical relation,
|
||||||
|
using semantic well formedness of substitutions to handle the context.
|
||||||
|
|
||||||
|
\begin{definition}[Semantic typing]
|
||||||
|
\begin{enumerate}[rightmargin=\leftmargin] \leavevmode
|
||||||
|
\item $[[v]]$ semantically has type $[[A]]$ under context $[[G]]$,
|
||||||
|
written $[[G ⊧ v : A]]$, if for every $[[s]]$ such that $[[G ⊧ s]]$,
|
||||||
|
there exists an interpretation $[[⟦A⟧ ↘ P]]$ such that $[[v{s} ∈ P]]$.
|
||||||
|
\item $[[m]]$ semantically has type $[[B]]$ under context $[[G]]$,
|
||||||
|
written $[[G ⊧ m : B]]$, if for every $[[s]]$ such that $[[G ⊧ s]]$,
|
||||||
|
there exists an interpretation $[[⟦B⟧ ↘ P]]$ such that $[[m{s} ∈ P]]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
Semantic typing follows exactly the same shape of rules as syntactic typing,
|
||||||
|
so I present them here as admissible rules.
|
||||||
|
All the hard work happens in these lemmas;
|
||||||
|
the fundamental theorem of soundness of syntactic typing with respect to semantic typing
|
||||||
|
then follows directly.
|
||||||
|
Normalization holds as an easy corollary.
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[S]{$[[G ⊧ v : A]]$}{admissible semantic value typing}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[S]{$[[G ⊧ m : B]]$}{admissible semantic computation typing}{Force,Arr,App,Ret,Let,Case}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By construction using prior lemmas,
|
||||||
|
in particular \rref{SRs-Let} in case \rref*{S-Let};
|
||||||
|
\nameref{lem:interp} in cases \rref*{S-Var,S-Inl,S-Inr,S-Lam};
|
||||||
|
\nameref{lem:det} in cases \rref*{S-Lam,S-App};
|
||||||
|
\nameref{lem:closure} in cases \rref*{S-Thunk,S-Lam,S-Let,S-Case}; and
|
||||||
|
\nameref{lem:adequacy} in cases \rref*{S-Lam,S-Let,S-Case}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{theorem}[Soundness] \label{thm:soundness} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $[[G ⊢ v : A]]$ then $[[G ⊧ v : A]]$.
|
||||||
|
\item If $[[G ⊢ m : B]]$ then $[[G ⊧ m : B]]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{theorem}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the syntactic typing derivations,
|
||||||
|
using the admissible semantic typing rules.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{corollary}[Normalization] \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $[[G ⊢ v : A]]$ then $[[v ∈ SN]]$.
|
||||||
|
\item If $[[G ⊢ m : B]]$ then $[[m ∈ SN]]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{corollary}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By \nameref{thm:soundness},
|
||||||
|
using the identity substitution and \rref{S-Nil},
|
||||||
|
the well typed terms inhabit the semantic interpretations of their types.
|
||||||
|
Then by \nameref{lem:adequacy},
|
||||||
|
they are also strongly normalizing.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\section{Strong Normalization as an Accessibility Relation} \label{sec:sn-acc}
|
||||||
|
|
||||||
|
\drules[sn]{$[[v ∈ sn]], [[m ∈ sn]]$}{strongly normalizing terms}{Val,Com}
|
||||||
|
\drules[sr]{$[[m ⤳' n]]$}{strong head reduction}{Thunk,Lam,Ret,Inl,Inr,App,Let}
|
||||||
|
\drules[ne]{$[[m ∈ ne]]$}{neutral computations}{Force,App,Let,Case}
|
||||||
|
|
||||||
|
\begin{mathpar}
|
||||||
|
\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drule[]{sn-App-invOne}
|
||||||
|
\drule[]{sn-App-invTwo}
|
||||||
|
\drule[]{sn-Let-invOne}
|
||||||
|
\drule[]{sn-Let-invTwo}
|
||||||
|
\end{mathpar}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the premises of strongly normal terms,
|
||||||
|
using congruence of single-step reduction.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{definition}[Neutral values]
|
||||||
|
A value is neutral, written $[[v ∈ ne]]$, if it is a variable.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
\begin{lemma}[Preservation] \label{lem:preservation} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $[[v ⇝ w]]$ and $[[v ∈ ne]]$ then $[[w ∈ ne]]$.
|
||||||
|
\item If $[[m ⇝ n]]$ and $[[m ∈ ne]]$ then $[[n ∈ ne]]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the single-step reductions.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{definition}[Strongly neutral computations]
|
||||||
|
A strongly neutral computation, written $[[m ∈ sne]]$,
|
||||||
|
is a computation that is both neutral and strongly normalizing,
|
||||||
|
\ie $[[m ∈ ne]]$ and $[[m ∈ sn]]$.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[sn]{$[[v ∈ sn]]$}{admissible strongly normal values}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[sn]{$[[m ∈ sn]]$}{admissible strongly normal computations}{Lam,Ret,Force,App,Let,Case}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
\Rref{sn-App,sn-Let,sn-Case} are proven by double induction
|
||||||
|
on the two derivations of strongly normal terms.
|
||||||
|
Intuitively, we want to show that if the conclusion steps,
|
||||||
|
then it steps to a strongly normal term,
|
||||||
|
knowing by the induction hypotheses that if their subterms reduce,
|
||||||
|
then they also reduce to strongly normal terms.
|
||||||
|
Neutrality of the term in head position eliminates cases where the conclusion $\beta$-reduces,
|
||||||
|
leaving only the congruent reductions.
|
||||||
|
Because single-step reduction only steps in one subterm,
|
||||||
|
we only need the induction hypothesis for that reducing subterm,
|
||||||
|
so the double induction is really a lexicographic induction on the two derivations.
|
||||||
|
We additionally require \nameref{lem:preservation} to carry along neutrality
|
||||||
|
when the heads reduce in cases \rref*{sn-App,sn-Let}.
|
||||||
|
All other cases are direct by construction
|
||||||
|
or by induction on their sole premise.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
% admissible rules missing backward closure \rref{SN-Red}
|
||||||
|
|
||||||
|
\begin{lemma}[Antisubstitution (\textsf{sn})] \label{lem:antisubst-sn}
|
||||||
|
If $[[m{x ↦ v} ∈ sn]]$ and $[[v ∈ sn]]$ then $[[m ∈ sn]]$.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $[[m{x ↦ v} ∈ sn]]$.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[sn]{$[[m ∈ sn]]$}{head expansion}{Force-Thunk,App-Lam,Let-Ret,Case-Inl,Case-Inr}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
\Rref{sn-Force-Thunk} holds directly by induction on the premise;
|
||||||
|
the remaining proofs are more complex.
|
||||||
|
First, given the premise $[[m{x ↦ v} ∈ sn]]$ (or $[[n{z ↦ v}]]$),
|
||||||
|
use \nameref{lem:antisubst-sn} to obtain $[[m ∈ sn]]$.
|
||||||
|
Then proceed by double (or triple) induction on the derivations of
|
||||||
|
$[[v ∈ sn]]$ and $[[m ∈ sn]]$ (and $[[n ∈ sn]]$ for the case rules).
|
||||||
|
Similarly to the admissible strongly normal rules,
|
||||||
|
these are lexicographic inductions,
|
||||||
|
except $[[m{x ↦ v} ∈ sn]]$ (or $[[n{z ↦ v}]]$)
|
||||||
|
is used to satisfy the $\beta$-reduction cases.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Confluence] \label{lem:confluence}
|
||||||
|
If $[[m ⇝ n1]]$ and $[[m ⤳' n2]]$, then either $[[n1]] = [[n2]]$,
|
||||||
|
or there exists some $[[m']]$ such that
|
||||||
|
$[[n1 ⤳' m']]$ and $[[n2 ⇝ m']]$.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $[[m ⤳' n2]]$,
|
||||||
|
then by cases on the derivation of $[[m ⇝ n1]]$.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{mathpar}
|
||||||
|
\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\fbox{$[[m ∈ sn]]$} \hfill \textit{backward closure in head position} \\
|
||||||
|
\drule[width=0.45\textwidth]{sn-App-bwd}
|
||||||
|
\drule[width=0.55\textwidth]{sn-Let-bwd}
|
||||||
|
\end{mathpar}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
First, use \rref{sn-App-inv,sn-Let-inv} to obtain $[[m ∈ sn]]$.
|
||||||
|
Then proceed by double induction on the derivations of
|
||||||
|
$[[m ∈ sn]]$ and $[[v ∈ sn]]$/$[[n ∈ sn]]$,
|
||||||
|
again as lexicographic induction.
|
||||||
|
We want to show that if the conclusion steps,
|
||||||
|
then it steps to a strongly normal term.
|
||||||
|
Strong reduction of the head position eliminates the cases of $\beta$-reduction,
|
||||||
|
leaving the cases where the head position steps or the other position steps.
|
||||||
|
If the head position steps, we use \nameref{lem:confluence}
|
||||||
|
to join the strong reduction and the single-step reduction together,
|
||||||
|
then use the first induction hypothesis.
|
||||||
|
Otherwise, we use the second induction hypothesis.
|
||||||
|
We need the last premise to step through either of the subterms,
|
||||||
|
since we have no congruence rule for when the head position is not neutral.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Backward closure] \label{lem:closure}
|
||||||
|
If $[[m ⤳' n]]$ and $[[n ∈ sn]]$ then $[[m ∈ sn]]$.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $[[m ⤳' n]]$.
|
||||||
|
The cases correspond exactly to each of
|
||||||
|
\rref{sn-Force-Thunk,sn-App-Lam,sn-Let-Ret,sn-Case-Inl,sn-Case-Inr,sn-App-bwd,sn-Let-bwd}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Soundness (\textsf{SNe})] \label{lem:sound-sne}
|
||||||
|
If $[[m ∈ SNe]]$ then $[[m ∈ ne]]$.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $[[m ∈ SNe]]$.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{theorem}[Soundness (\textsf{SN})] \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $[[m ∈ SNe]]$ then $[[m ∈ sn]]$.
|
||||||
|
\item If $[[v ∈ SN]]$ then $[[v ∈ sn]]$.
|
||||||
|
\item If $[[m ∈ SN]]$ then $[[m ∈ sn]]$.
|
||||||
|
\item If $[[m ⤳ n]]$ then $[[m ⤳' n]]$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{theorem}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the derivations of
|
||||||
|
$[[m ∈ SNe]]$, $[[v ∈ SN]]$, $[[m ∈ SN]]$, and $[[m ⤳ n]]$.
|
||||||
|
The cases for the first three correspond to the admissible strongly normal rules,
|
||||||
|
using \nameref{lem:sound-sne} as needed,
|
||||||
|
except for the \rref*{SN-Red} case, which uses \nameref{lem:closure}.
|
||||||
|
The cases for strong reduction hold by construction.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{corollary}
|
||||||
|
If $[[G ⊢ v : A]]$ then $[[v ∈ sn]]$,
|
||||||
|
and if $[[G ⊢ m : B]]$ then $[[m ∈ sn]]$.
|
||||||
|
\end{corollary}
|
||||||
|
|
||||||
|
\section{Discussion} \label{sec:discussion}
|
||||||
|
|
||||||
|
\end{document}
|
|
@ -0,0 +1,791 @@
|
||||||
|
embed
|
||||||
|
{{ tex-preamble
|
||||||
|
\newcommand{\gap}{\:}
|
||||||
|
\newcommand{\kw}[1]{ \mathsf{#1} }
|
||||||
|
}}
|
||||||
|
|
||||||
|
metavar x, y, z ::=
|
||||||
|
{{ com term variables }}
|
||||||
|
{{ lex alphanum }}
|
||||||
|
|
||||||
|
grammar
|
||||||
|
|
||||||
|
v, w :: 'val_' ::= {{ com values }}
|
||||||
|
| x :: :: Var
|
||||||
|
| unit :: :: Unit
|
||||||
|
{{ tex \kw{unit} }}
|
||||||
|
| inl v :: :: Inl
|
||||||
|
{{ tex \kw{inl} \gap [[v]] }}
|
||||||
|
| inr v :: :: Inr
|
||||||
|
{{ tex \kw{inr} \gap [[v]] }}
|
||||||
|
| thunk m :: :: Thunk
|
||||||
|
{{ tex \kw{thunk} \gap [[m]] }}
|
||||||
|
| ( v ) :: S :: Parens
|
||||||
|
{{ com parentheses }}
|
||||||
|
{{ tex ([[v]]) }}
|
||||||
|
| v { s } :: S :: Subst
|
||||||
|
{{ tex [[v]][ [[s]] ]}}
|
||||||
|
|
||||||
|
m, n :: 'com_' ::= {{ com computations }}
|
||||||
|
| force v :: :: Force
|
||||||
|
{{ tex \kw{force} \gap [[v]] }}
|
||||||
|
| λ x . m :: :: Lam
|
||||||
|
(+ bind x in m +)
|
||||||
|
{{ tex \lambda [[x]] \mathpunct{.} [[m]] }}
|
||||||
|
| m v :: :: App
|
||||||
|
{{ tex [[m]] \gap [[v]] }}
|
||||||
|
| ret v :: :: Ret
|
||||||
|
{{ tex \kw{return} \gap [[v]] }}
|
||||||
|
| let x m n :: :: Let
|
||||||
|
(+ bind x in n +)
|
||||||
|
{{ tex \kw{let} \gap [[x]] \leftarrow [[m]] \gap \kw{in} \gap [[n]] }}
|
||||||
|
| case v | y . m | z . n :: :: Case
|
||||||
|
(+ bind y in m +)
|
||||||
|
(+ bind z in n +)
|
||||||
|
{{ tex \kw{case} \gap [[v]] \gap \kw{of} \gap \lbrace \kw{inl} \gap [[y]] \Rightarrow [[m]] \mathrel{;} \kw{inr} \gap [[z]] \Rightarrow [[n]] \rbrace }}
|
||||||
|
| ( m ) :: S :: Parens
|
||||||
|
{{ com parentheses }}
|
||||||
|
{{ tex ([[m]]) }}
|
||||||
|
| m { s } :: S :: Subst
|
||||||
|
{{ tex [[m]][ [[s]] ]}}
|
||||||
|
|
||||||
|
A :: 'valtype_' ::= {{ com value types }}
|
||||||
|
| Unit :: :: Unit
|
||||||
|
{{ tex \kw{Unit} }}
|
||||||
|
| A1 + A2 :: :: Sum
|
||||||
|
{{ tex [[A1]] + [[A2]] }}
|
||||||
|
| U B :: :: U
|
||||||
|
{{ tex \kw{U} \gap [[B]] }}
|
||||||
|
|
||||||
|
B :: 'comtype_' ::= {{ com computation types }}
|
||||||
|
| F A :: :: F
|
||||||
|
{{ tex \kw{F} \gap [[A]] }}
|
||||||
|
| A → B :: :: Arr
|
||||||
|
{{ tex [[A]] \rightarrow [[B]] }}
|
||||||
|
|
||||||
|
s {{ tex \sigma }} :: 'subst_' ::= {{ com substitutions }}
|
||||||
|
| • :: :: Nil
|
||||||
|
{{ com identity substitution }}
|
||||||
|
{{ tex \cdot }}
|
||||||
|
| s , x ↦ v :: :: Cons
|
||||||
|
{{ com substitution extension }}
|
||||||
|
{{ tex [[s]], [[x]] \mapsto [[v]] }}
|
||||||
|
| x ↦ v :: S :: Single
|
||||||
|
{{ com single substitution }}
|
||||||
|
{{ tex [[x]] \mapsto [[v]] }}
|
||||||
|
| ⇑ s :: :: Lift
|
||||||
|
{{ com lifting substitution }}
|
||||||
|
{{ tex \mathop{\Uparrow} [[s]] }}
|
||||||
|
|
||||||
|
G {{ tex \Gamma }}, D {{ tex \Delta }} :: 'ctxt_' ::= {{ com contexts }}
|
||||||
|
| • :: :: Nil
|
||||||
|
{{ com empty context }}
|
||||||
|
{{ tex \cdot }}
|
||||||
|
| G , x : A :: :: Cons
|
||||||
|
{{ com context extension }}
|
||||||
|
{{ tex [[G]], [[x]] \mathbin{:} [[A]] }}
|
||||||
|
|
||||||
|
P, Q :: 'set_' ::=
|
||||||
|
| { v | formula } :: :: valset
|
||||||
|
{{ tex \lbrace [[v]] \mid [[formula]] \rbrace }}
|
||||||
|
| { m | formula } :: :: comset
|
||||||
|
{{ tex \lbrace [[m]] \mid [[formula]] \rbrace }}
|
||||||
|
|
||||||
|
formula :: 'formula_' ::=
|
||||||
|
| judgement :: :: judgement
|
||||||
|
| formula1 ∧ formula2 :: :: and
|
||||||
|
{{ tex [[formula1]] \wedge [[formula2]] }}
|
||||||
|
| formula1 ∨ formula2 :: :: or
|
||||||
|
{{ tex [[formula1]] \vee [[formula2]] }}
|
||||||
|
| formula1 ⇒ formula2 :: :: implies
|
||||||
|
{{ tex [[formula1]] \Rightarrow [[formula2]] }}
|
||||||
|
| x : A ∈ G :: :: in
|
||||||
|
{{ tex [[x]] : [[A]] \in [[G]] }}
|
||||||
|
| v = w :: :: equals
|
||||||
|
{{ tex [[v]] = [[w]] }}
|
||||||
|
| v ∈ P :: :: valin
|
||||||
|
{{ tex [[v]] \in [[P]] }}
|
||||||
|
| m ∈ P :: :: comin
|
||||||
|
{{ tex [[m]] \in [[P]] }}
|
||||||
|
| ∀ v . formula :: :: valforall
|
||||||
|
{{ tex \forall [[v]] \mathpunct{.} [[formula]] }}
|
||||||
|
| ∀ m . formula :: :: comforall
|
||||||
|
{{ tex \forall [[m]] \mathpunct{.} [[formula]] }}
|
||||||
|
| ∃ v . formula :: :: valexists
|
||||||
|
{{ tex \exists [[v]] \mathpunct{.} [[formula]] }}
|
||||||
|
| ∃ m . formula :: :: comexists
|
||||||
|
{{ tex \exists [[m]] \mathpunct{.} [[formula]] }}
|
||||||
|
| ( formula ) :: :: parentheses
|
||||||
|
{{ tex ( [[formula ]] ) }}
|
||||||
|
| (# formula #) :: :: sparentheses
|
||||||
|
{{ tex [[formula]] }}
|
||||||
|
|
||||||
|
%% Inductive definition of strong normalization %%
|
||||||
|
|
||||||
|
defns
|
||||||
|
SN :: '' ::=
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ∈ SNe :: :: SNeVal :: 'SNe_'
|
||||||
|
{{ tex [[v]] \in \kw{SNe} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------- :: Var
|
||||||
|
x ∈ SNe
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ∈ SNe :: :: SNeCom :: 'SNe_'
|
||||||
|
{{ tex [[m]] \in \kw{SNe} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------------- :: Force
|
||||||
|
force x ∈ SNe
|
||||||
|
|
||||||
|
m ∈ SNe
|
||||||
|
v ∈ SN
|
||||||
|
--------- :: App
|
||||||
|
m v ∈ SNe
|
||||||
|
|
||||||
|
m ∈ SNe
|
||||||
|
n ∈ SN
|
||||||
|
--------------- :: Let
|
||||||
|
let x m n ∈ SNe
|
||||||
|
|
||||||
|
m ∈ SN
|
||||||
|
n ∈ SN
|
||||||
|
------------------------ :: Case
|
||||||
|
case x | y.m | z.n ∈ SNe
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ∈ SN :: :: SNVal :: 'SN_'
|
||||||
|
{{ tex [[v]] \in \kw{SN} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------ :: Var
|
||||||
|
x ∈ SN
|
||||||
|
|
||||||
|
--------- :: Unit
|
||||||
|
unit ∈ SN
|
||||||
|
|
||||||
|
v ∈ SN
|
||||||
|
---------- :: Inl
|
||||||
|
inl v ∈ SN
|
||||||
|
|
||||||
|
v ∈ SN
|
||||||
|
---------- :: Inr
|
||||||
|
inr v ∈ SN
|
||||||
|
|
||||||
|
m ∈ SN
|
||||||
|
------------ :: Thunk
|
||||||
|
thunk m ∈ SN
|
||||||
|
|
||||||
|
% inversion
|
||||||
|
|
||||||
|
force v ∈ SN
|
||||||
|
------------ :: Force_inv
|
||||||
|
v ∈ SN
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ∈ SN :: :: SNCom :: 'SN_'
|
||||||
|
{{ tex [[m]] \in \kw{SN} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
m ∈ SN
|
||||||
|
---------- :: Lam
|
||||||
|
λx. m ∈ SN
|
||||||
|
|
||||||
|
v ∈ SN
|
||||||
|
---------- :: Ret
|
||||||
|
ret v ∈ SN
|
||||||
|
|
||||||
|
m ∈ SNe
|
||||||
|
------- :: SNe
|
||||||
|
m ∈ SN
|
||||||
|
|
||||||
|
m ⤳ n
|
||||||
|
n ∈ SN
|
||||||
|
------ :: Red
|
||||||
|
m ∈ SN
|
||||||
|
|
||||||
|
% backward closure
|
||||||
|
|
||||||
|
m ⤳* n
|
||||||
|
n ∈ SN
|
||||||
|
------- :: Reds
|
||||||
|
m ∈ SN
|
||||||
|
|
||||||
|
% extensionality
|
||||||
|
|
||||||
|
m x ∈ SN
|
||||||
|
-------- :: Ext
|
||||||
|
m ∈ SN
|
||||||
|
|
||||||
|
% lifting
|
||||||
|
|
||||||
|
G ⊧ s
|
||||||
|
G, x : A ⊧ m : B
|
||||||
|
---------------- :: Lift
|
||||||
|
m{⇑ s} ∈ SN
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ⤳ n :: :: SR :: 'SR_'
|
||||||
|
{{ tex [[m]] \leadsto [[n]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
-------------------- :: Thunk
|
||||||
|
force (thunk m) ⤳ m
|
||||||
|
|
||||||
|
v ∈ SN
|
||||||
|
--------------------- :: Lam
|
||||||
|
(λx. m) v ⤳ m{x ↦ v}
|
||||||
|
|
||||||
|
v ∈ SN
|
||||||
|
--------------------------- :: Ret
|
||||||
|
let x (ret v) m ⤳ m{x ↦ v}
|
||||||
|
|
||||||
|
v ∈ SN
|
||||||
|
n ∈ SN
|
||||||
|
------------------------------------ :: Inl
|
||||||
|
case (inl v) | y.m | z.n ⤳ m{y ↦ v}
|
||||||
|
|
||||||
|
v ∈ SN
|
||||||
|
m ∈ SN
|
||||||
|
------------------------------------ :: Inr
|
||||||
|
case (inr v) | y.m | z.n ⤳ n{z ↦ v}
|
||||||
|
|
||||||
|
m ⤳ n
|
||||||
|
---------- :: App
|
||||||
|
m v ⤳ n v
|
||||||
|
|
||||||
|
m ⤳ m'
|
||||||
|
----------------------- :: Let
|
||||||
|
let x m n ⤳ let x m' n
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ⤳* n :: :: SRs :: 'SRs_'
|
||||||
|
{{ tex [[m]] \leadsto^* [[n]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------- :: Refl
|
||||||
|
m ⤳* m
|
||||||
|
|
||||||
|
m ⤳ m'
|
||||||
|
m' ⤳* n
|
||||||
|
-------- :: Trans
|
||||||
|
m ⤳* n
|
||||||
|
|
||||||
|
% admissible
|
||||||
|
|
||||||
|
m ⤳ n
|
||||||
|
------- :: Once
|
||||||
|
m ⤳* n
|
||||||
|
|
||||||
|
m ⤳* m'
|
||||||
|
m' ⤳* n
|
||||||
|
-------- :: Trans'
|
||||||
|
m ⤳* n
|
||||||
|
|
||||||
|
% congruence rules
|
||||||
|
|
||||||
|
m ⤳* n
|
||||||
|
----------- :: App
|
||||||
|
m v ⤳* n v
|
||||||
|
|
||||||
|
m ⤳* m'
|
||||||
|
------------------------ :: Let
|
||||||
|
let x m n ⤳* let x m' n
|
||||||
|
|
||||||
|
%% Logical relation and semantic typing %%
|
||||||
|
|
||||||
|
defns
|
||||||
|
LR :: '' ::=
|
||||||
|
|
||||||
|
defn
|
||||||
|
⟦ A ⟧ ↘ P :: :: ValType :: 'LR_'
|
||||||
|
{{ tex \mathopen{\llbracket} [[A]] \mathclose{\rrbracket} \searrow [[P]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------------------------------------- :: Unit
|
||||||
|
⟦ Unit ⟧ ↘ { v | v ∈ SNe ∨ v = unit }
|
||||||
|
|
||||||
|
⟦ A1 ⟧ ↘ P
|
||||||
|
⟦ A2 ⟧ ↘ Q
|
||||||
|
----------------------------------------------------------------------------------------------------------- :: Sum
|
||||||
|
⟦ A1 + A2 ⟧ ↘ { v | v ∈ SNe ∨ (# (∃w. (# v = inl w ∧ w ∈ P #)) ∨ (∃w. (# v = inr w ∧ w ∈ Q #)) #) }
|
||||||
|
|
||||||
|
⟦ B ⟧ ↘ P
|
||||||
|
----------------------------- :: U
|
||||||
|
⟦ U B ⟧ ↘ { v | force v ∈ P }
|
||||||
|
|
||||||
|
defn
|
||||||
|
⟦ B ⟧ ↘ P :: :: ComType :: 'LR_'
|
||||||
|
{{ tex \mathopen{\llbracket} [[B]] \mathclose{\rrbracket} \searrow [[P]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
⟦ A ⟧ ↘ P
|
||||||
|
--------------------------------------------------------------------------------- :: F
|
||||||
|
⟦ F A ⟧ ↘ { m | (∃n. (# m ⤳* n ∧ n ∈ SNe #)) ∨ (∃v. (# m ⤳* ret v ∧ v ∈ P #)) }
|
||||||
|
|
||||||
|
⟦ A ⟧ ↘ P
|
||||||
|
⟦ B ⟧ ↘ Q
|
||||||
|
--------------------------------------------- :: Arr
|
||||||
|
⟦ A → B ⟧ ↘ { m | ∀v. (# v ∈ P ⇒ m v ∈ Q #) }
|
||||||
|
|
||||||
|
defns
|
||||||
|
LRs :: '' ::=
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ∈ ⟦ A ⟧ :: :: ValTypes :: 'LR'_'
|
||||||
|
{{ tex [[v]] \in \mathopen{\llbracket} [[A]] \mathclose{\rrbracket} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------------ :: Unit_var
|
||||||
|
x ∈ ⟦ Unit ⟧
|
||||||
|
|
||||||
|
--------------- :: Unit_unit
|
||||||
|
unit ∈ ⟦ Unit ⟧
|
||||||
|
|
||||||
|
--------------- :: Sum_var
|
||||||
|
x ∈ ⟦ A1 + A2 ⟧
|
||||||
|
|
||||||
|
v ∈ ⟦ A1 ⟧
|
||||||
|
------------------- :: Sum_inl
|
||||||
|
inl v ∈ ⟦ A1 + A2 ⟧
|
||||||
|
|
||||||
|
v ∈ ⟦ A2 ⟧
|
||||||
|
------------------- :: Sum_inr
|
||||||
|
inr v ∈ ⟦ A1 + A2 ⟧
|
||||||
|
|
||||||
|
force v ∈ ⟦ B ⟧
|
||||||
|
--------------- :: Force
|
||||||
|
v ∈ ⟦ U B ⟧
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ∈ ⟦ B ⟧ :: :: ComTypes :: 'LR'_'
|
||||||
|
{{ tex [[m]] \in \mathopen{\llbracket} [[B]] \mathclose{\rrbracket} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
m ⤳* n
|
||||||
|
n ∈ SNe
|
||||||
|
----------- :: F_var
|
||||||
|
m ∈ ⟦ F A ⟧
|
||||||
|
|
||||||
|
m ⤳* ret v
|
||||||
|
v ∈ ⟦ A ⟧
|
||||||
|
----------- :: F_ret
|
||||||
|
m ∈ ⟦ F A ⟧
|
||||||
|
|
||||||
|
∀v. (# v ∈ ⟦ A ⟧ ⇒ m v ∈ ⟦ B ⟧ #)
|
||||||
|
--------------------------------- :: Arr
|
||||||
|
m ∈ ⟦ A → B ⟧
|
||||||
|
|
||||||
|
defns
|
||||||
|
Sem :: '' ::=
|
||||||
|
|
||||||
|
defn
|
||||||
|
G ⊧ s :: :: SemCtxt :: 'S_'
|
||||||
|
{{ tex [[G]] \vDash [[s]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
----- :: Nil
|
||||||
|
G ⊧ •
|
||||||
|
|
||||||
|
G ⊧ s
|
||||||
|
⟦ A ⟧ ↘ P
|
||||||
|
v ∈ P
|
||||||
|
------------------- :: Cons
|
||||||
|
G, x : A ⊧ s, x ↦ v
|
||||||
|
|
||||||
|
defn
|
||||||
|
G ⊧ v : A :: :: SemVal :: 'S_'
|
||||||
|
{{ tex [[G]] \vDash [[v]] : [[A]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
x : A ∈ G
|
||||||
|
--------- :: Var
|
||||||
|
G ⊧ x : A
|
||||||
|
|
||||||
|
--------------- :: Unit
|
||||||
|
G ⊧ unit : Unit
|
||||||
|
|
||||||
|
G ⊧ v : A1
|
||||||
|
------------------- :: Inl
|
||||||
|
G ⊧ inl v : A1 + A2
|
||||||
|
|
||||||
|
G ⊧ v : A2
|
||||||
|
------------------- :: Inr
|
||||||
|
G ⊧ inr v : A1 + A2
|
||||||
|
|
||||||
|
G ⊧ m : B
|
||||||
|
----------------- :: Thunk
|
||||||
|
G ⊧ thunk m : U B
|
||||||
|
|
||||||
|
defn
|
||||||
|
G ⊧ m : B :: :: SemCom :: 'S_'
|
||||||
|
{{ tex [[G]] \vDash [[m]] : [[B]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
G ⊧ v : U B
|
||||||
|
--------------- :: Force
|
||||||
|
G ⊧ force v : B
|
||||||
|
|
||||||
|
G, x : A ⊧ m : B
|
||||||
|
----------------- :: Arr
|
||||||
|
G ⊧ λx. m : A → B
|
||||||
|
|
||||||
|
G ⊧ m : A → B
|
||||||
|
G ⊧ v : A
|
||||||
|
-------------- :: App
|
||||||
|
G ⊧ m v : B
|
||||||
|
|
||||||
|
G ⊧ v : A
|
||||||
|
---------------- :: Ret
|
||||||
|
G ⊧ ret v : F A
|
||||||
|
|
||||||
|
G ⊧ m : F A
|
||||||
|
G, x : A ⊧ n : B
|
||||||
|
----------------- :: Let
|
||||||
|
G ⊧ let x m n : B
|
||||||
|
|
||||||
|
G ⊧ v : A1 + A2
|
||||||
|
G, y : A1 ⊧ m : B
|
||||||
|
G, z : A2 ⊧ n : B
|
||||||
|
-------------------------- :: Case
|
||||||
|
G ⊧ case v | y.m | z.n : B
|
||||||
|
|
||||||
|
%% Syntactic typing %%
|
||||||
|
|
||||||
|
defns
|
||||||
|
Typing :: '' ::=
|
||||||
|
|
||||||
|
defn
|
||||||
|
G ⊢ v : A :: :: ValWt :: 'T_'
|
||||||
|
{{ tex [[G]] \vdash [[v]] : [[A]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
x : A ∈ G
|
||||||
|
--------- :: Var
|
||||||
|
G ⊢ x : A
|
||||||
|
|
||||||
|
--------------- :: Unit
|
||||||
|
G ⊢ unit : Unit
|
||||||
|
|
||||||
|
G ⊢ v : A1
|
||||||
|
------------------- :: Inl
|
||||||
|
G ⊢ inl v : A1 + A2
|
||||||
|
|
||||||
|
G ⊢ v : A2
|
||||||
|
------------------- :: Inr
|
||||||
|
G ⊢ inr v : A1 + A2
|
||||||
|
|
||||||
|
G ⊢ m : B
|
||||||
|
----------------- :: Thunk
|
||||||
|
G ⊢ thunk m : U B
|
||||||
|
|
||||||
|
defn
|
||||||
|
G ⊢ m : B :: :: ComWt :: 'T_'
|
||||||
|
{{ tex [[G]] \vdash [[m]] : [[B]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
G ⊢ v : U B
|
||||||
|
--------------- :: Force
|
||||||
|
G ⊢ force v : B
|
||||||
|
|
||||||
|
G, x : A ⊢ m : B
|
||||||
|
----------------- :: Lam
|
||||||
|
G ⊢ λx. m : A → B
|
||||||
|
|
||||||
|
G ⊢ m : A → B
|
||||||
|
G ⊢ v : A
|
||||||
|
-------------- :: App
|
||||||
|
G ⊢ m v : B
|
||||||
|
|
||||||
|
G ⊢ v : A
|
||||||
|
---------------- :: Ret
|
||||||
|
G ⊢ ret v : F A
|
||||||
|
|
||||||
|
G ⊢ m : F A
|
||||||
|
G, x : A ⊢ n : B
|
||||||
|
----------------- :: Let
|
||||||
|
G ⊢ let x m n : B
|
||||||
|
|
||||||
|
G ⊢ v : A1 + A2
|
||||||
|
G, y : A1 ⊢ m : B
|
||||||
|
G, z : A2 ⊢ n : B
|
||||||
|
-------------------------- :: Case
|
||||||
|
G ⊢ case v | y.m | z.n : B
|
||||||
|
|
||||||
|
%% Reduction %%
|
||||||
|
|
||||||
|
defns
|
||||||
|
Red :: '' ::=
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ⇝ w :: :: StepVal :: 'StepVal_'
|
||||||
|
{{ tex [[v]] \rightsquigarrow [[w]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ⇝ n :: :: StepCom :: 'StepCom_'
|
||||||
|
{{ tex [[m]] \rightsquigarrow [[n]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ⇝* w :: :: StepVals :: 'StepVals_'
|
||||||
|
{{ tex [[v]] \rightsquigarrow^* [[w]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ⇝* n :: :: StepComs :: 'StepComs_'
|
||||||
|
{{ tex [[m]] \rightsquigarrow^* [[n]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
%% Accessibility definition of strong normalization %%
|
||||||
|
|
||||||
|
defns
|
||||||
|
sn :: '' ::=
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ∈ sn :: :: snVal :: 'sn_'
|
||||||
|
{{ tex [[v]] \in \kw{sn} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
∀w. (# v ⇝ w ⇒ w ∈ sn #)
|
||||||
|
------------------------ :: Val
|
||||||
|
v ∈ sn
|
||||||
|
|
||||||
|
% inversion
|
||||||
|
|
||||||
|
force v ∈ sn
|
||||||
|
------------ :: Force_inv
|
||||||
|
v ∈ sn
|
||||||
|
|
||||||
|
m v ∈ sn
|
||||||
|
-------- :: App_inv2
|
||||||
|
v ∈ sn
|
||||||
|
|
||||||
|
% congruence
|
||||||
|
|
||||||
|
------ :: Var
|
||||||
|
x ∈ sn
|
||||||
|
|
||||||
|
--------- :: Unit
|
||||||
|
unit ∈ sn
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
---------- :: Inl
|
||||||
|
inl v ∈ sn
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
---------- :: Inr
|
||||||
|
inr v ∈ sn
|
||||||
|
|
||||||
|
m ∈ sn
|
||||||
|
------------ :: Thunk
|
||||||
|
thunk m ∈ sn
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ∈ sn :: :: snCom :: 'sn_'
|
||||||
|
{{ tex [[m]] \in \kw{sn} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
∀n. (# m ⇝ n ⇒ n ∈ sn #)
|
||||||
|
------------------------ :: Com
|
||||||
|
m ∈ sn
|
||||||
|
|
||||||
|
% inversion
|
||||||
|
|
||||||
|
m v ∈ sn
|
||||||
|
-------- :: App_inv1
|
||||||
|
m ∈ sn
|
||||||
|
|
||||||
|
let x m n ∈ sn
|
||||||
|
-------------- :: Let_inv1
|
||||||
|
m ∈ sn
|
||||||
|
|
||||||
|
let x m n ∈ sn
|
||||||
|
-------------- :: Let_inv2
|
||||||
|
n ∈ sn
|
||||||
|
|
||||||
|
% antisubstitution
|
||||||
|
|
||||||
|
m{x ↦ v} ∈ sn
|
||||||
|
v ∈ sn
|
||||||
|
------------- :: antisubst
|
||||||
|
m ∈ sn
|
||||||
|
|
||||||
|
% expansion
|
||||||
|
|
||||||
|
m ∈ sn
|
||||||
|
-------------------- :: Force_Thunk
|
||||||
|
force (thunk m) ∈ sn
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
m{x ↦ v} ∈ sn
|
||||||
|
-------------- :: App_Lam
|
||||||
|
(λx. m) v ∈ sn
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
m{x ↦ v} ∈ sn
|
||||||
|
-------------------- :: Let_Ret
|
||||||
|
let x (ret v) m ∈ sn
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
m{y ↦ v} ∈ sn
|
||||||
|
n ∈ sn
|
||||||
|
----------------------------- :: Case_Inl
|
||||||
|
case (inl v) | y.m | z.n ∈ sn
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
m ∈ sn
|
||||||
|
n{z ↦ v} ∈ sn
|
||||||
|
----------------------------- :: Case_Inr
|
||||||
|
case (inr v) | y.m | z.n ∈ sn
|
||||||
|
|
||||||
|
% closure
|
||||||
|
|
||||||
|
m ⤳' n
|
||||||
|
v ∈ sn
|
||||||
|
n v ∈ sn
|
||||||
|
-------- :: App_bwd
|
||||||
|
m v ∈ sn
|
||||||
|
|
||||||
|
m ⤳' m'
|
||||||
|
n ∈ sn
|
||||||
|
let x m' n ∈ sn
|
||||||
|
--------------- :: Let_bwd
|
||||||
|
let x m n ∈ sn
|
||||||
|
|
||||||
|
m ⤳' n
|
||||||
|
n ∈ sn
|
||||||
|
------- :: closure
|
||||||
|
m ∈ sn
|
||||||
|
|
||||||
|
% congruence
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
------------ :: Force
|
||||||
|
force v ∈ sn
|
||||||
|
|
||||||
|
m ∈ sn
|
||||||
|
---------- :: Lam
|
||||||
|
λx. m ∈ sn
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
---------- :: Ret
|
||||||
|
ret v ∈ sn
|
||||||
|
|
||||||
|
m ∈ sne
|
||||||
|
v ∈ sn
|
||||||
|
-------- :: App
|
||||||
|
m v ∈ sn
|
||||||
|
|
||||||
|
m ∈ sne
|
||||||
|
n ∈ sn
|
||||||
|
-------------- :: Let
|
||||||
|
let x m n ∈ sn
|
||||||
|
|
||||||
|
v ∈ sne
|
||||||
|
m ∈ sn
|
||||||
|
n ∈ sn
|
||||||
|
----------------------- :: Case
|
||||||
|
case v | y.m | z.n ∈ sn
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ⤳' n :: :: sr :: 'sr_'
|
||||||
|
{{ tex [[m]] \leadsto_{ \kw{sn} } [[n]] }}
|
||||||
|
by
|
||||||
|
|
||||||
|
--------------------- :: Thunk
|
||||||
|
force (thunk m) ⤳' m
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
---------------------- :: Lam
|
||||||
|
(λx. m) v ⤳' m{x ↦ v}
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
---------------------------- :: Ret
|
||||||
|
let x (ret v) m ⤳' m{x ↦ v}
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
n ∈ sn
|
||||||
|
------------------------------------- :: Inl
|
||||||
|
case (inl v) | y.m | z.n ⤳' m{y ↦ v}
|
||||||
|
|
||||||
|
v ∈ sn
|
||||||
|
m ∈ sn
|
||||||
|
------------------------------------- :: Inr
|
||||||
|
case (inr v) | y.m | z.n ⤳' n{z ↦ v}
|
||||||
|
|
||||||
|
m ⤳' n
|
||||||
|
----------- :: App
|
||||||
|
m v ⤳' n v
|
||||||
|
|
||||||
|
m ⤳' m'
|
||||||
|
------------------------ :: Let
|
||||||
|
let x m n ⤳' let x m' n
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ∈ ne :: :: neVal :: 'ne_'
|
||||||
|
{{ tex [[v]] \in \kw{ne} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------ :: Var
|
||||||
|
x ∈ ne
|
||||||
|
|
||||||
|
% preservation
|
||||||
|
|
||||||
|
v ⇝ w
|
||||||
|
v ∈ ne
|
||||||
|
------ :: StepVal
|
||||||
|
w ∈ ne
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ∈ ne :: :: neCom :: 'ne_'
|
||||||
|
{{ tex [[m]] \in \kw{ne} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------------ :: Force
|
||||||
|
force x ∈ ne
|
||||||
|
|
||||||
|
m ∈ ne
|
||||||
|
-------- :: App
|
||||||
|
m v ∈ ne
|
||||||
|
|
||||||
|
m ∈ ne
|
||||||
|
-------------- :: Let
|
||||||
|
let x m n ∈ ne
|
||||||
|
|
||||||
|
------------------ :: Case
|
||||||
|
case x | y.m | z.n ∈ ne
|
||||||
|
|
||||||
|
% preservation
|
||||||
|
|
||||||
|
m ⇝ n
|
||||||
|
n ∈ ne
|
||||||
|
------ :: StepCom
|
||||||
|
m ∈ ne
|
||||||
|
|
||||||
|
% embedding
|
||||||
|
|
||||||
|
m ∈ SNe
|
||||||
|
------- :: SNe
|
||||||
|
m ∈ ne
|
||||||
|
|
||||||
|
defn
|
||||||
|
v ∈ sne :: :: sneVal :: 'sneval_'
|
||||||
|
{{ tex [[v]] \in \kw{sne} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
------- :: sne
|
||||||
|
x ∈ sne
|
||||||
|
|
||||||
|
defn
|
||||||
|
m ∈ sne :: :: sneCom :: 'snecom_'
|
||||||
|
{{ tex [[m]] \in \kw{sne} }}
|
||||||
|
by
|
||||||
|
|
||||||
|
m ∈ ne
|
||||||
|
m ∈ sn
|
||||||
|
------- :: sne
|
||||||
|
m ∈ sne
|
|
@ -0,0 +1,650 @@
|
||||||
|
\documentclass{article}
|
||||||
|
|
||||||
|
\usepackage[supertabular]{ottalt}
|
||||||
|
\let\newlist\relax
|
||||||
|
\let\renewlist\relax
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage{mlmodern}
|
||||||
|
\usepackage[margin=1in]{geometry}
|
||||||
|
\usepackage{enumitem,float,booktabs,xspace,doi}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage[capitalize,nameinlink]{cleveref}
|
||||||
|
\usepackage{mathpartir,mathtools,stmaryrd}
|
||||||
|
|
||||||
|
\setlist{nosep}
|
||||||
|
\hypersetup{
|
||||||
|
colorlinks=true,
|
||||||
|
urlcolor=blue,
|
||||||
|
linkcolor=magenta,
|
||||||
|
citecolor=teal
|
||||||
|
}
|
||||||
|
\urlstyle{tt}
|
||||||
|
|
||||||
|
\newtheorem{theorem}{Theorem}
|
||||||
|
\newtheorem{lemma}[theorem]{Lemma}
|
||||||
|
\newtheorem{corollary}[theorem]{Corollary}
|
||||||
|
\theoremstyle{definition}
|
||||||
|
\newtheorem{definition}{Definition}
|
||||||
|
|
||||||
|
\newcommand{\ie}{\textit{i.e.}\@\xspace}
|
||||||
|
\newcommand{\ala}{\textit{\`a la}\@\xspace}
|
||||||
|
\newcommand{\apriori}{\textit{a priori}\@\xspace}
|
||||||
|
\newcommand{\aposteriori}{\textit{a posteriori}\@\xspace}
|
||||||
|
|
||||||
|
\title{Strong Normalization for \\ Simply Typed Call-by-Push-Value}
|
||||||
|
\author{Jonathan Chan}
|
||||||
|
\date{}
|
||||||
|
|
||||||
|
\inputott{rules}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\section{Introduction}
|
||||||
|
|
||||||
|
The goal of this project is to mechanize a proof of strong normalization for call-by-push-value (CBPV).
|
||||||
|
It follows work by Forster, Sch\"afer, Spies, and Stark (TODO: cite) on mechanizing the metatheory of CBPV in Rocq,
|
||||||
|
but instead adapts the proof technique from POPLMark Reloaded (TODO: cite).
|
||||||
|
|
||||||
|
Both proofs, and mine, follow the same sequence of steps:
|
||||||
|
we define a logical relation that semantically interpret types as sets of terms,
|
||||||
|
show that these sets are backward closed by reduction and that they contain only strongly normalizing terms,
|
||||||
|
prove a fundamental soundness theorem that places well typed terms in the semantic interpretations of their types,
|
||||||
|
and conclude that well typed terms must be strongly normalizing.
|
||||||
|
The difference lies in \emph{how strong normalization} (and reduction) is defined.
|
||||||
|
The Rocq mechanization uses a traditional definition of strong normalization as an accessibility relation,
|
||||||
|
while POPLMark Reloaded and this project use an inductive characterization of strong normalization,
|
||||||
|
then prove it sound with respect to the traditional definition.
|
||||||
|
|
||||||
|
In contrast to both prior works, which use Rocq, Agda, or Beluga,
|
||||||
|
this project is mechanized in Lean.
|
||||||
|
A secondary purpose of this project is to assess the capabilities of Lean for PL metatheory,
|
||||||
|
especially when making heavy use of mutually defined inductive types.
|
||||||
|
I have implemented a mutual induction tactic for Lean (TODO: link),
|
||||||
|
and the mutual values and computations of CBPV,
|
||||||
|
combined with the even more complex mutual inductives from POPLMark Reloaded,
|
||||||
|
make it an attractive test case to test the tactic's robustness.
|
||||||
|
|
||||||
|
This report is divided in roughly the same shape as the proof development.
|
||||||
|
\Cref{sec:syntax} introduces the syntax and the typing rules for CBPV (\texttt{Syntax.lean}, \texttt{Typing.lean}).
|
||||||
|
Then the inductive characterization of strong normalization is defined in \cref{sec:sn-ind} (\texttt{NormalInd.lean}),
|
||||||
|
followed by the logical relation in \cref{sec:lr} (\texttt{OpenSemantics.lean}).
|
||||||
|
The central theorem of strong normalization is proven in \cref{sec:soundness}
|
||||||
|
as a corollary of the fundamental theorem for the logical relation (\texttt{Soundness.lean}, \texttt{Normalization.lean}).
|
||||||
|
To ensure that the inductive characterization is correct,
|
||||||
|
\cref{sec:sn-acc} shows that it implies the traditional definition of strong normalization (\texttt{NormalAcc.lean}).
|
||||||
|
This latter definition and proof depends on small-step reduction on open terms,
|
||||||
|
whose properties are omitted here (\texttt{Reduction.lean}).
|
||||||
|
In general, I gloss over details about substitution and reduction,
|
||||||
|
since I'm interested in presenting the structure of the strong normalization proof
|
||||||
|
and not the minutiae of syntax and binding.
|
||||||
|
Finally, I discuss the merits of this proof technique
|
||||||
|
and the challenges posed by using Lean in \cref{sec:discussion}.
|
||||||
|
|
||||||
|
\section{Syntax and Typing} \label{sec:syntax}
|
||||||
|
|
||||||
|
\begin{align*}
|
||||||
|
\ottnt{A} &\Coloneqq \kw{Unit} \mid \ottnt{A_{{\mathrm{1}}}} + \ottnt{A_{{\mathrm{2}}}} \mid \kw{U} \gap \ottnt{B} & \textit{value types} \\
|
||||||
|
\ottnt{B} &\Coloneqq \ottnt{A} \rightarrow \ottnt{B} \mid \kw{F} \gap \ottnt{A} & \textit{computation types} \\
|
||||||
|
\ottnt{v}, \ottnt{w} &\Coloneqq \ottmv{x} \mid \kw{unit} \mid \kw{inl} \gap \ottnt{v} \mid \kw{inr} \gap \ottnt{v} \mid \kw{thunk} \gap \ottnt{m} & \textit{values} \\
|
||||||
|
\ottnt{m}, \ottnt{n} &\Coloneqq \kw{force} \gap \ottnt{v} \mid \lambda \ottmv{x} \mathpunct{.} \ottnt{m} \mid \ottnt{m} \gap \ottnt{v} \mid \kw{return} \gap \ottnt{v} & \textit{computations} \\
|
||||||
|
& \mid \kw{let} \gap \ottmv{x} \leftarrow \ottnt{m} \gap \kw{in} \gap \ottnt{n} \\
|
||||||
|
& \mid \kw{case} \gap \ottnt{v} \gap \kw{of} \gap \lbrace \kw{inl} \gap \ottmv{y} \Rightarrow \ottnt{m} \mathrel{;} \kw{inr} \gap \ottmv{z} \Rightarrow \ottnt{n} \rbrace \\
|
||||||
|
\Gamma &\Coloneqq \cdot \mid \Gamma , \ottmv{x} \mathbin{:} \ottnt{A} & \textit{typing contexts} \\
|
||||||
|
\sigma &\Coloneqq \cdot \mid \sigma , \ottmv{x} \mapsto \ottnt{v} & \textit{simultaneous substitutions}
|
||||||
|
\end{align*}
|
||||||
|
|
||||||
|
The grammar of the CBPV for this project is given above.
|
||||||
|
Terms and their types are divided between \emph{values} and \emph{computations}.
|
||||||
|
Values are variables, unit, injections into a sum type, or a thunked computation,
|
||||||
|
while computations are forcing thunks,
|
||||||
|
functions, applications, returning values, binding returned values,
|
||||||
|
and case analysis on sums.
|
||||||
|
There are only value variables and no computation variables,
|
||||||
|
since they represent terms that require no more work to be done on them ready to be substituted in,
|
||||||
|
and typing contexts similarly only contain value types.
|
||||||
|
I use $t$ to refer to terms that may be either values or computations.
|
||||||
|
|
||||||
|
Although the syntax is presented nominally,
|
||||||
|
the mechanization uses an unscoped de Bruijn indexed representation of variables,
|
||||||
|
along with simultaneous substitutions $\sigma$ mapping variables to values,
|
||||||
|
with $ \cdot $ as the identity substitution.
|
||||||
|
Applying a substitution is represented as $ \ottnt{v} [ \sigma ] $ and $ \ottnt{m} [ \sigma ] $,
|
||||||
|
and implemented in terms of renamings,
|
||||||
|
which are mappings from variables to other variables.
|
||||||
|
|
||||||
|
This is not the usual complete CBPV language,
|
||||||
|
since it's missing both value tuples and computation tuples.
|
||||||
|
I exclude them because they are syntactically not much more interesting than returns,
|
||||||
|
whose eliminator is shaped like pattern matching on a singleton value tuple,
|
||||||
|
and than thunks,
|
||||||
|
whose eliminator is shaped like projection on a singleton computation tuple.
|
||||||
|
In contrast, I do include sums, which represent the only way a computation can branch.
|
||||||
|
|
||||||
|
The typing rules below are standard for the values and computations included.
|
||||||
|
The judgements for values and computations are defined mutually,
|
||||||
|
just as are the types and the terms.
|
||||||
|
|
||||||
|
\drules[T]{$ \Gamma \vdash \ottnt{v} : \ottnt{A} $}{value typing}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[T]{$ \Gamma \vdash \ottnt{m} : \ottnt{B} $}{computation typing}{Force,Lam,App,Ret,Let,Case}
|
||||||
|
|
||||||
|
\section{Strong Normalization as an Inductive Definition} \label{sec:sn-ind}
|
||||||
|
|
||||||
|
The idea behind the inductive characterization of strong normalization
|
||||||
|
is to describe case by case when a term is strongly normal,
|
||||||
|
rather than showing \aposteriori which terms are strongly normal.
|
||||||
|
This is done in conjunction with defining strongly neutral terms,
|
||||||
|
which are blocked from $\beta$-reduction,
|
||||||
|
and strong head reduction,
|
||||||
|
which expands the set from normal forms
|
||||||
|
to terms which must reduce to normal forms.
|
||||||
|
|
||||||
|
The general recipe for defining these for CBPV is as follows:
|
||||||
|
\begin{itemize}[rightmargin=\leftmargin]
|
||||||
|
\item The only strongly neutral values are variables.
|
||||||
|
\item Strongly neutral computations are eliminators
|
||||||
|
whose head positions are strongly neutral,
|
||||||
|
while all other subterms are strongly normal.
|
||||||
|
\item Strongly normal values are constructors
|
||||||
|
whose subterms are strongly normal,
|
||||||
|
or strongly neutral values, \ie variables.
|
||||||
|
\item Strongly normal computations are constructors
|
||||||
|
whose subterms are strongly normal,
|
||||||
|
or strongly neutral computations,
|
||||||
|
or computations which reduce to strongly normal computations
|
||||||
|
(backward closure).
|
||||||
|
\item Strong head reduction consists of $\beta$ reductions
|
||||||
|
for all eliminators around the corresponding constructors,
|
||||||
|
and congruent reductions in head positions.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Additionally, strong reduction requires premises asserting that
|
||||||
|
the subterms that may ``disappear'' after reduction be strongly normal
|
||||||
|
so that backward closure actually closes over strongly normal terms.
|
||||||
|
These subterms are the values that get substituted into a computation,
|
||||||
|
which may disappear if the computation never actually uses the binding,
|
||||||
|
as well as computation branches not taken.
|
||||||
|
|
||||||
|
Because we're dealing with CBPV, values have no $\beta$ reductions,
|
||||||
|
so there's no need for head reduction of values as there are no heads.
|
||||||
|
Furthermore, there is only one strongly neutral value,
|
||||||
|
so we inline the definition as a variable where needed,
|
||||||
|
but also write it as $ \ottnt{v} \in \kw{SNe} $ for symmetry as appropriate.
|
||||||
|
Otherwise, the remaining four judgements are defined mutually below.
|
||||||
|
|
||||||
|
\drules[SNe]{$ \ottnt{m} \in \kw{SNe} $}{strongly neutral computations}{Force,App,Let,Case}
|
||||||
|
\drules[SN]{$ \ottnt{v} \in \kw{SN} $}{strongly normal values}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[SN]{$ \ottnt{m} \in \kw{SN} $}{strongly normal computations}{Lam,Ret,SNe,Red}
|
||||||
|
\drules[SR]{$ \ottnt{m} \leadsto \ottnt{n} $}{strong head reduction}{Thunk,Lam,Ret,Inl,Inr,App,Let}
|
||||||
|
\drules[SRs]{$ \ottnt{m} \leadsto^* \ottnt{n} $}{reflexive, transitive closure of head reduction}{Refl,Trans}
|
||||||
|
|
||||||
|
We also need the reflexive, transitive closure of head reduction,
|
||||||
|
defined as a separate inductive above.
|
||||||
|
Now we show a few simple lemmas about it,
|
||||||
|
along with an inversion lemma for forcing
|
||||||
|
(other inversion lemmas hold, but this is the only one we need).
|
||||||
|
I present them below as judgement pseudorules
|
||||||
|
using a dashed line to indicate that they are admissible rules.
|
||||||
|
These are all proven either by construction
|
||||||
|
or by induction on the first premise.
|
||||||
|
|
||||||
|
\begin{mathpar}
|
||||||
|
\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drule[]{SRs-Once}
|
||||||
|
\drule[]{SRs-TransPP}
|
||||||
|
\drule[]{SRs-App}
|
||||||
|
\drule[]{SRs-Let}
|
||||||
|
\drule[]{SN-Reds}
|
||||||
|
\drule[]{SN-Force-inv}
|
||||||
|
\end{mathpar}
|
||||||
|
|
||||||
|
The most important property of strongly normal terms that we need is antirenaming,
|
||||||
|
which states that undoing a renaming does not change the term's
|
||||||
|
normalization or reduction behaviour.
|
||||||
|
A crucial property that follows is extensionality of applications,
|
||||||
|
which is an inversion lemma specifically when the application argument is a variable.
|
||||||
|
|
||||||
|
\begin{lemma}[Antirenaming] \label{thm:antisubst}
|
||||||
|
Let $\sigma$ be a renaming,
|
||||||
|
\ie a substitution mapping variables to variables.
|
||||||
|
Then the following hold:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $ \ottnt{m} [ \sigma ] \in \kw{SNe} $ then $ \ottnt{m} \in \kw{SNe} $.
|
||||||
|
\item If $ \ottnt{v} [ \sigma ] \in \kw{SN} $ then $ \ottnt{v} \in \kw{SN} $.
|
||||||
|
\item If $ \ottnt{m} [ \sigma ] \in \kw{SN} $ then $ \ottnt{m} \in \kw{SN} $.
|
||||||
|
\item If $ \ottnt{m} [ \sigma ] \leadsto \ottnt{n} $ then there exists some $\ottnt{n'}$
|
||||||
|
such that $\ottnt{n} = \ottnt{n'} [ \sigma ] $ and $ \ottnt{m} \leadsto \ottnt{n'} $.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the four derivations of
|
||||||
|
$ \ottnt{m} [ \sigma ] \in \kw{SNe} $, $ \ottnt{v} [ \sigma ] \in \kw{SN} $, $ \ottnt{m} [ \sigma ] \in \kw{SN} $, and $ \ottnt{m} [ \sigma ] \leadsto \ottnt{n} $.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{corollary}[Extensionality] \label{cor:ext}
|
||||||
|
If $ \ottnt{m} \gap \ottmv{x} \in \kw{SN} $ then $ \ottnt{m} \in \kw{SN} $.
|
||||||
|
\end{corollary}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of strongly normal values.
|
||||||
|
The possible cases are \rref*{SN-SNe,SN-Red}.
|
||||||
|
Destructing the premise of the former gives $ \ottnt{m} \in \kw{SNe} $,
|
||||||
|
and we conclude using \rref{SN-SNe} again.
|
||||||
|
In the latter case, we have $ \ottnt{m} \gap \ottmv{x} \leadsto \ottnt{n} $ and $ \ottnt{n} \in \kw{SN} $;
|
||||||
|
destructing on the reduction yields the possible cases
|
||||||
|
\rref{SR-Lam,SR-App}.
|
||||||
|
In the first case, we have $ \ottnt{m} [ \ottmv{x} \mapsto \ottnt{v} ] \in \kw{SN} $,
|
||||||
|
so the goal holds by \nameref{thm:antisubst}.
|
||||||
|
In the second case, we have $ \ottnt{m} \leadsto \ottnt{n} $ and $ \ottnt{n} \gap \ottmv{x} \in \kw{SN} $,
|
||||||
|
so by the induction hypothesis, we have $ \ottnt{n} \in \kw{SN} $,
|
||||||
|
and we conclude using \rref{SN-Red}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\section{Logical Relation on Open Terms} \label{sec:lr}
|
||||||
|
|
||||||
|
The next step is to define a logical relation that semantically interprets types
|
||||||
|
as sets of open terms.
|
||||||
|
The key property we need from these sets is that they contain only strongly normal terms.
|
||||||
|
Because we are working with open terms to prove normalization
|
||||||
|
and not just termination of evaluation of closed terms,
|
||||||
|
we need to consider variables and strongly neutral terms.
|
||||||
|
Having no other information about them other than their strong neutrality,
|
||||||
|
we require that the interpretation sets always contain all strongly neutral terms.
|
||||||
|
|
||||||
|
The logical relation on simple types can be defined by induction on the structure of the type.
|
||||||
|
However, I want to maximize the amount of mutual inductives used in this project,
|
||||||
|
so we instead define the logical relation as an inductive binary relation
|
||||||
|
between the type and the set of terms of its interpretation,
|
||||||
|
denoted as $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $ and $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{P} $ below.
|
||||||
|
I use set builder notation to define the sets and set membership,
|
||||||
|
but they are implemented in the mechanization as functions
|
||||||
|
that take terms and return propositions and as function applications.
|
||||||
|
Here, the conjunctions ($\wedge$), disjunctions ($\vee$), equalities ($=$), implications ($\Rightarrow$),
|
||||||
|
and universal ($\forall$) and existential ($\exists$) quantifiers
|
||||||
|
are part of the metatheory, not part of the object language.
|
||||||
|
|
||||||
|
\drules[LR]{$ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $}{semantic interpretation of value types}{Unit,U,Sum}
|
||||||
|
\drules[LR]{$ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{P} $}{semantic interpretation of computation types}{F,Arr}
|
||||||
|
|
||||||
|
The terms in the interpretation of a type can be characterized in two different ways:
|
||||||
|
by what constructor of that type they reduce to,
|
||||||
|
or by how they act when eliminated by an eliminator for that type.
|
||||||
|
For the former, we need to explicitly include the possibility of the term being strongly neutral.
|
||||||
|
I chose the following characterizations because they seemed the simplest to me,
|
||||||
|
but the alternate choices likely work as well.
|
||||||
|
|
||||||
|
\begin{itemize}[noitemsep,rightmargin=\leftmargin]
|
||||||
|
\item Values in the interpretation of the unit type
|
||||||
|
are either variables or the unit value.
|
||||||
|
\item Values are in the interpretation of the $ \kw{U} \gap \ottnt{B} $ type
|
||||||
|
if they can be forced to computations in the interpretation of the $\ottnt{B}$ type.
|
||||||
|
\item Values in the interpretation of the sum type $ \ottnt{A_{{\mathrm{1}}}} + \ottnt{A_{{\mathrm{2}}}} $ are either variables,
|
||||||
|
left injections whose values are in the interpretation of $\ottnt{A_{{\mathrm{1}}}}$,
|
||||||
|
or right injections whose values are in that of $\ottnt{A_{{\mathrm{2}}}}$.
|
||||||
|
\item Computations in the interpretation of the $ \kw{F} \gap \ottnt{A} $ type
|
||||||
|
reduce to either a neutral computation
|
||||||
|
or a return whose value is in the interpretation of $\ottnt{A}$.
|
||||||
|
\item Computations are in the interpretation of the function type $ \ottnt{A} \rightarrow \ottnt{B} $
|
||||||
|
if applying them to values in the interpretation of $\ottnt{A}$
|
||||||
|
yields computations in the interpretation of $\ottnt{B}$.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
By this description, it sounds like the logical relation can be presented
|
||||||
|
directly as a relation between a type and a term;
|
||||||
|
this presentation is given in \cref{fig:lr-alt}.
|
||||||
|
Unfortunately, this is not well defined,
|
||||||
|
since the logical relation appears in a negative position
|
||||||
|
(to the left of an implication) in the premise of \rref{LRPP-Arr}.
|
||||||
|
The alternate presentation can be interpreted as a function
|
||||||
|
match on the term and the type and returning the conjunction of its premises,
|
||||||
|
but I wanted to use a mutually defined inductive definition.
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\fbox{$ \ottnt{v} \in \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} $} \quad \fbox{$ \ottnt{m} \in \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} $} \hfill \textit{} \\
|
||||||
|
\begin{mathpar}
|
||||||
|
\drule[]{LRPP-Unit-var}
|
||||||
|
\drule[]{LRPP-Unit-unit}
|
||||||
|
\drule[]{LRPP-Sum-var}
|
||||||
|
\drule[]{LRPP-Sum-inl}
|
||||||
|
\drule[]{LRPP-Sum-inr}
|
||||||
|
\drule[]{LRPP-Force}
|
||||||
|
\drule[]{LRPP-F-var}
|
||||||
|
\drule[]{LRPP-F-ret}
|
||||||
|
\drule[]{LRPP-Arr}
|
||||||
|
\end{mathpar}
|
||||||
|
\caption{Alternate presentation of the logical relation}
|
||||||
|
\label{fig:lr-alt}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Using the inductive presentation of the logical relation,
|
||||||
|
there are three easy properties to show:
|
||||||
|
interpretability, which states that all types have an interpretation;
|
||||||
|
determinism, which states that the interpretation indeed behaves like a function
|
||||||
|
from types to sets of terms;
|
||||||
|
and backward closure, which states that the interpretations of computation types
|
||||||
|
are backward closed under multi-step head reduction.
|
||||||
|
The last property is why \rref{LRPP-F-var} needs to include
|
||||||
|
computations that \emph{reduce to} strongly neutral terms or returns,
|
||||||
|
not merely ones that are such terms.
|
||||||
|
|
||||||
|
\begin{lemma}[Interpretability] \label{lem:interp} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Given $\ottnt{A}$, there exists $\ottnt{P}$ such that $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $.
|
||||||
|
\item Given $\ottnt{B}$, there exists $\ottnt{P}$ such that $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{P} $.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the types $\ottnt{A}$ and $\ottnt{B}$.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Determinism] \label{lem:det} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $ and $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{Q} $ then $\ottnt{P} = \ottnt{Q}$.
|
||||||
|
\item If $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{P} $ and $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{Q} $ then $\ottnt{P} = \ottnt{Q}$.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the first derivations of the logical relation,
|
||||||
|
then by cases on the second derivations.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Backward closure] \label{lem:closure}
|
||||||
|
Given $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{P} $ and $ \ottnt{m} \leadsto^* \ottnt{n} $,
|
||||||
|
if $ \ottnt{n} \in \ottnt{P} $ then $ \ottnt{m} \in \ottnt{P} $.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of the logical relation.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
The final key property is adequacy,
|
||||||
|
which states that the interpretations of types
|
||||||
|
must contain all strongly neutral terms
|
||||||
|
and must contain only strongly normal terms.
|
||||||
|
Such sets are said to be \emph{reducibility candidates}.
|
||||||
|
|
||||||
|
\begin{definition}[Reducibility candidates]
|
||||||
|
A reducibility candidate is a set of terms $\ottnt{P}$ where,
|
||||||
|
given a term $t$,
|
||||||
|
if $ t \in \kw{SNe} $ then $ t \in \ottnt{P} $, and
|
||||||
|
if $ t \in \ottnt{P} $ then $ t \in \kw{SN} $.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
\begin{lemma}[Adequacy] \label{lem:adequacy} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $ then $\ottnt{P}$ is a reducibility candidate.
|
||||||
|
\item If $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{P} $ then $\ottnt{P}$ is a reducibility candidate.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the derivations of the logical relation.
|
||||||
|
\Rref{SN-Force-inv} is used in the \rref*{S-U} case,
|
||||||
|
while \rref{SN-Reds} is used in the \rref{S-F} case.
|
||||||
|
In the \rref*{S-Arr} case on $ \ottnt{A} \rightarrow \ottnt{B} $,
|
||||||
|
where $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $ and $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{Q} $,
|
||||||
|
to show the second part of its interpretation being a reducibility candidate,
|
||||||
|
we are given $\ottnt{m}$ such that for every $ \ottnt{v} \in \ottnt{P} $, $ \ottnt{m} \gap \ottnt{v} \in \ottnt{Q} $,
|
||||||
|
and the goal is to show that $ \ottnt{m} \in \kw{SN} $.
|
||||||
|
By the induction hypotheses, picking an arbitrary variable $\ottmv{x}$,
|
||||||
|
we have that $ \ottmv{x} \in \ottnt{P} $ (since it is neutral) and that $ \ottnt{m} \gap \ottmv{x} \in \kw{SN} $.
|
||||||
|
Then the goal holds by \nameref{cor:ext}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\section{Semantic Typing and the Fundamental Theorem} \label{sec:soundness}
|
||||||
|
|
||||||
|
Now that we know that the interpretations contain only strongly normal terms,
|
||||||
|
our goal is to show that well typed terms inhabit the interpretations of their types.
|
||||||
|
We first define what it means for a substitution to be
|
||||||
|
semantically well formed with respect to a context.
|
||||||
|
|
||||||
|
\begin{definition}[Semantic well-formedness of substitutions]
|
||||||
|
A substitution $\sigma$ is well formed with respect to a context $\Gamma$,
|
||||||
|
written $ \Gamma \vDash \sigma $, if for every $ \ottmv{x} : \ottnt{A} \in \Gamma $ and $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $,
|
||||||
|
we have $ \ottmv{x} [ \sigma ] \in \ottnt{P} $.
|
||||||
|
In short, the substitution maps variables in the context
|
||||||
|
to values in the interpretations of their types.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
These judgements can be built up inductively,
|
||||||
|
as demonstrated by the below admissible rules,
|
||||||
|
which are proven by cases.
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[S]{$ \Gamma \vDash \sigma $}{admissible semantic substitution well-formedness}{Nil,Cons}
|
||||||
|
}
|
||||||
|
|
||||||
|
Then we can define semantic typing in terms of the logical relation,
|
||||||
|
using semantic well formedness of substitutions to handle the context.
|
||||||
|
|
||||||
|
\begin{definition}[Semantic typing]
|
||||||
|
\begin{enumerate}[rightmargin=\leftmargin] \leavevmode
|
||||||
|
\item $\ottnt{v}$ semantically has type $\ottnt{A}$ under context $\Gamma$,
|
||||||
|
written $ \Gamma \vDash \ottnt{v} : \ottnt{A} $, if for every $\sigma$ such that $ \Gamma \vDash \sigma $,
|
||||||
|
there exists an interpretation $ \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} \searrow \ottnt{P} $ such that $ \ottnt{v} [ \sigma ] \in \ottnt{P} $.
|
||||||
|
\item $\ottnt{m}$ semantically has type $\ottnt{B}$ under context $\Gamma$,
|
||||||
|
written $ \Gamma \vDash \ottnt{m} : \ottnt{B} $, if for every $\sigma$ such that $ \Gamma \vDash \sigma $,
|
||||||
|
there exists an interpretation $ \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} \searrow \ottnt{P} $ such that $ \ottnt{m} [ \sigma ] \in \ottnt{P} $.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
Semantic typing follows exactly the same shape of rules as syntactic typing,
|
||||||
|
so I present them here as admissible rules.
|
||||||
|
All the hard work happens in these lemmas;
|
||||||
|
the fundamental theorem of soundness of syntactic typing with respect to semantic typing
|
||||||
|
then follows directly.
|
||||||
|
Normalization holds as an easy corollary.
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[S]{$ \Gamma \vDash \ottnt{v} : \ottnt{A} $}{admissible semantic value typing}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[S]{$ \Gamma \vDash \ottnt{m} : \ottnt{B} $}{admissible semantic computation typing}{Force,Arr,App,Ret,Let,Case}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By construction using prior lemmas,
|
||||||
|
in particular \rref{SRs-Let} in case \rref*{S-Let};
|
||||||
|
\nameref{lem:interp} in cases \rref*{S-Var,S-Inl,S-Inr,S-Lam};
|
||||||
|
\nameref{lem:det} in cases \rref*{S-Lam,S-App};
|
||||||
|
\nameref{lem:closure} in cases \rref*{S-Thunk,S-Lam,S-Let,S-Case}; and
|
||||||
|
\nameref{lem:adequacy} in cases \rref*{S-Lam,S-Let,S-Case}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{theorem}[Soundness] \label{thm:soundness} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $ \Gamma \vdash \ottnt{v} : \ottnt{A} $ then $ \Gamma \vDash \ottnt{v} : \ottnt{A} $.
|
||||||
|
\item If $ \Gamma \vdash \ottnt{m} : \ottnt{B} $ then $ \Gamma \vDash \ottnt{m} : \ottnt{B} $.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{theorem}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the syntactic typing derivations,
|
||||||
|
using the admissible semantic typing rules.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{corollary}[Normalization] \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $ \Gamma \vdash \ottnt{v} : \ottnt{A} $ then $ \ottnt{v} \in \kw{SN} $.
|
||||||
|
\item If $ \Gamma \vdash \ottnt{m} : \ottnt{B} $ then $ \ottnt{m} \in \kw{SN} $.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{corollary}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By \nameref{thm:soundness},
|
||||||
|
using the identity substitution and \rref{S-Nil},
|
||||||
|
the well typed terms inhabit the semantic interpretations of their types.
|
||||||
|
Then by \nameref{lem:adequacy},
|
||||||
|
they are also strongly normalizing.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\section{Strong Normalization as an Accessibility Relation} \label{sec:sn-acc}
|
||||||
|
|
||||||
|
\drules[sn]{$ \ottnt{v} \in \kw{sn} , \ottnt{m} \in \kw{sn} $}{strongly normalizing terms}{Val,Com}
|
||||||
|
\drules[sr]{$ \ottnt{m} \leadsto_{ \kw{sn} } \ottnt{n} $}{strong head reduction}{Thunk,Lam,Ret,Inl,Inr,App,Let}
|
||||||
|
\drules[ne]{$ \ottnt{m} \in \kw{ne} $}{neutral computations}{Force,App,Let,Case}
|
||||||
|
|
||||||
|
\begin{mathpar}
|
||||||
|
\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drule[]{sn-App-invOne}
|
||||||
|
\drule[]{sn-App-invTwo}
|
||||||
|
\drule[]{sn-Let-invOne}
|
||||||
|
\drule[]{sn-Let-invTwo}
|
||||||
|
\end{mathpar}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the premises of strongly normal terms,
|
||||||
|
using congruence of single-step reduction.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{definition}[Neutral values]
|
||||||
|
A value is neutral, written $ \ottnt{v} \in \kw{ne} $, if it is a variable.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
\begin{lemma}[Preservation] \label{lem:preservation} \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $ \ottnt{v} \rightsquigarrow \ottnt{w} $ and $ \ottnt{v} \in \kw{ne} $ then $ \ottnt{w} \in \kw{ne} $.
|
||||||
|
\item If $ \ottnt{m} \rightsquigarrow \ottnt{n} $ and $ \ottnt{m} \in \kw{ne} $ then $ \ottnt{n} \in \kw{ne} $.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the single-step reductions.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{definition}[Strongly neutral computations]
|
||||||
|
A strongly neutral computation, written $ \ottnt{m} \in \kw{sne} $,
|
||||||
|
is a computation that is both neutral and strongly normalizing,
|
||||||
|
\ie $ \ottnt{m} \in \kw{ne} $ and $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
\end{definition}
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[sn]{$ \ottnt{v} \in \kw{sn} $}{admissible strongly normal values}{Var,Unit,Inl,Inr,Thunk}
|
||||||
|
\drules[sn]{$ \ottnt{m} \in \kw{sn} $}{admissible strongly normal computations}{Lam,Ret,Force,App,Let,Case}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
\Rref{sn-App,sn-Let,sn-Case} are proven by double induction
|
||||||
|
on the two derivations of strongly normal terms.
|
||||||
|
Intuitively, we want to show that if the conclusion steps,
|
||||||
|
then it steps to a strongly normal term,
|
||||||
|
knowing by the induction hypotheses that if their subterms reduce,
|
||||||
|
then they also reduce to strongly normal terms.
|
||||||
|
Neutrality of the term in head position eliminates cases where the conclusion $\beta$-reduces,
|
||||||
|
leaving only the congruent reductions.
|
||||||
|
Because single-step reduction only steps in one subterm,
|
||||||
|
we only need the induction hypothesis for that reducing subterm,
|
||||||
|
so the double induction is really a lexicographic induction on the two derivations.
|
||||||
|
We additionally require \nameref{lem:preservation} to carry along neutrality
|
||||||
|
when the heads reduce in cases \rref*{sn-App,sn-Let}.
|
||||||
|
All other cases are direct by construction
|
||||||
|
or by induction on their sole premise.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
% admissible rules missing backward closure \rref{SN-Red}
|
||||||
|
|
||||||
|
\begin{lemma}[Antisubstitution (\textsf{sn})] \label{lem:antisubst-sn}
|
||||||
|
If $ \ottnt{m} [ \ottmv{x} \mapsto \ottnt{v} ] \in \kw{sn} $ and $ \ottnt{v} \in \kw{sn} $ then $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $ \ottnt{m} [ \ottmv{x} \mapsto \ottnt{v} ] \in \kw{sn} $.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
{\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\drules[sn]{$ \ottnt{m} \in \kw{sn} $}{head expansion}{Force-Thunk,App-Lam,Let-Ret,Case-Inl,Case-Inr}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
\Rref{sn-Force-Thunk} holds directly by induction on the premise;
|
||||||
|
the remaining proofs are more complex.
|
||||||
|
First, given the premise $ \ottnt{m} [ \ottmv{x} \mapsto \ottnt{v} ] \in \kw{sn} $ (or $ \ottnt{n} [ \ottmv{z} \mapsto \ottnt{v} ] $),
|
||||||
|
use \nameref{lem:antisubst-sn} to obtain $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
Then proceed by double (or triple) induction on the derivations of
|
||||||
|
$ \ottnt{v} \in \kw{sn} $ and $ \ottnt{m} \in \kw{sn} $ (and $ \ottnt{n} \in \kw{sn} $ for the case rules).
|
||||||
|
Similarly to the admissible strongly normal rules,
|
||||||
|
these are lexicographic inductions,
|
||||||
|
except $ \ottnt{m} [ \ottmv{x} \mapsto \ottnt{v} ] \in \kw{sn} $ (or $ \ottnt{n} [ \ottmv{z} \mapsto \ottnt{v} ] $)
|
||||||
|
is used to satisfy the $\beta$-reduction cases.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Confluence] \label{lem:confluence}
|
||||||
|
If $ \ottnt{m} \rightsquigarrow \ottnt{n_{{\mathrm{1}}}} $ and $ \ottnt{m} \leadsto_{ \kw{sn} } \ottnt{n_{{\mathrm{2}}}} $, then either $\ottnt{n_{{\mathrm{1}}}} = \ottnt{n_{{\mathrm{2}}}}$,
|
||||||
|
or there exists some $\ottnt{m'}$ such that
|
||||||
|
$ \ottnt{n_{{\mathrm{1}}}} \leadsto_{ \kw{sn} } \ottnt{m'} $ and $ \ottnt{n_{{\mathrm{2}}}} \rightsquigarrow \ottnt{m'} $.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $ \ottnt{m} \leadsto_{ \kw{sn} } \ottnt{n_{{\mathrm{2}}}} $,
|
||||||
|
then by cases on the derivation of $ \ottnt{m} \rightsquigarrow \ottnt{n_{{\mathrm{1}}}} $.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{mathpar}
|
||||||
|
\mprset{fraction={-~}{-~}{-}}
|
||||||
|
\fbox{$ \ottnt{m} \in \kw{sn} $} \hfill \textit{backward closure in head position} \\
|
||||||
|
\drule[width=0.45\textwidth]{sn-App-bwd}
|
||||||
|
\drule[width=0.55\textwidth]{sn-Let-bwd}
|
||||||
|
\end{mathpar}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
First, use \rref{sn-App-inv,sn-Let-inv} to obtain $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
Then proceed by double induction on the derivations of
|
||||||
|
$ \ottnt{m} \in \kw{sn} $ and $ \ottnt{v} \in \kw{sn} $/$ \ottnt{n} \in \kw{sn} $,
|
||||||
|
again as lexicographic induction.
|
||||||
|
We want to show that if the conclusion steps,
|
||||||
|
then it steps to a strongly normal term.
|
||||||
|
Strong reduction of the head position eliminates the cases of $\beta$-reduction,
|
||||||
|
leaving the cases where the head position steps or the other position steps.
|
||||||
|
If the head position steps, we use \nameref{lem:confluence}
|
||||||
|
to join the strong reduction and the single-step reduction together,
|
||||||
|
then use the first induction hypothesis.
|
||||||
|
Otherwise, we use the second induction hypothesis.
|
||||||
|
We need the last premise to step through either of the subterms,
|
||||||
|
since we have no congruence rule for when the head position is not neutral.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Backward closure] \label{lem:closure}
|
||||||
|
If $ \ottnt{m} \leadsto_{ \kw{sn} } \ottnt{n} $ and $ \ottnt{n} \in \kw{sn} $ then $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $ \ottnt{m} \leadsto_{ \kw{sn} } \ottnt{n} $.
|
||||||
|
The cases correspond exactly to each of
|
||||||
|
\rref{sn-Force-Thunk,sn-App-Lam,sn-Let-Ret,sn-Case-Inl,sn-Case-Inr,sn-App-bwd,sn-Let-bwd}.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{lemma}[Soundness (\textsf{SNe})] \label{lem:sound-sne}
|
||||||
|
If $ \ottnt{m} \in \kw{SNe} $ then $ \ottnt{m} \in \kw{ne} $.
|
||||||
|
\end{lemma}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By induction on the derivation of $ \ottnt{m} \in \kw{SNe} $.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{theorem}[Soundness (\textsf{SN})] \leavevmode
|
||||||
|
\begin{enumerate}
|
||||||
|
\item If $ \ottnt{m} \in \kw{SNe} $ then $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
\item If $ \ottnt{v} \in \kw{SN} $ then $ \ottnt{v} \in \kw{sn} $.
|
||||||
|
\item If $ \ottnt{m} \in \kw{SN} $ then $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
\item If $ \ottnt{m} \leadsto \ottnt{n} $ then $ \ottnt{m} \leadsto_{ \kw{sn} } \ottnt{n} $.
|
||||||
|
\end{enumerate}
|
||||||
|
\end{theorem}
|
||||||
|
|
||||||
|
\begin{proof}
|
||||||
|
By mutual induction on the derivations of
|
||||||
|
$ \ottnt{m} \in \kw{SNe} $, $ \ottnt{v} \in \kw{SN} $, $ \ottnt{m} \in \kw{SN} $, and $ \ottnt{m} \leadsto \ottnt{n} $.
|
||||||
|
The cases for the first three correspond to the admissible strongly normal rules,
|
||||||
|
using \nameref{lem:sound-sne} as needed,
|
||||||
|
except for the \rref*{SN-Red} case, which uses \nameref{lem:closure}.
|
||||||
|
The cases for strong reduction hold by construction.
|
||||||
|
\end{proof}
|
||||||
|
|
||||||
|
\begin{corollary}
|
||||||
|
If $ \Gamma \vdash \ottnt{v} : \ottnt{A} $ then $ \ottnt{v} \in \kw{sn} $,
|
||||||
|
and if $ \Gamma \vdash \ottnt{m} : \ottnt{B} $ then $ \ottnt{m} \in \kw{sn} $.
|
||||||
|
\end{corollary}
|
||||||
|
|
||||||
|
\section{Discussion} \label{sec:discussion}
|
||||||
|
|
||||||
|
\end{document}
|
|
@ -0,0 +1,349 @@
|
||||||
|
%%
|
||||||
|
%% This is file `listproc.sty',
|
||||||
|
%% generated with the docstrip utility.
|
||||||
|
%%
|
||||||
|
%% The original source files were:
|
||||||
|
%%
|
||||||
|
%% listproc.dtx (with options: `package')
|
||||||
|
%%
|
||||||
|
%% Copyright (C) 2011 by Jesse A. Tov
|
||||||
|
%%
|
||||||
|
%% This file may be distributed and/or modified under the conditions of the
|
||||||
|
%% LaTeX Project Public License, either version 1.2 of this license or (at
|
||||||
|
%% your option) any later version. The latest version of this license is
|
||||||
|
%% in:
|
||||||
|
%%
|
||||||
|
%% http://www.latex-project.org/lppl.txt
|
||||||
|
%%
|
||||||
|
%% and version 1.2 or later is part of all distributions of LaTeX
|
||||||
|
%% version 1999/12/01 or later.
|
||||||
|
%%
|
||||||
|
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
|
||||||
|
\ProvidesPackage{listproc}[2011/08/03 v0.2 (list processing)]
|
||||||
|
\newcommand\newlist{\@lstp@def{}\newcommand}
|
||||||
|
\newcommand\renewlist{\@lstp@def{}\renewcommand}
|
||||||
|
\newcommand\deflist{\@lstp@def{}\def}
|
||||||
|
\newcommand\gdeflist{\@lstp@def\global\def}
|
||||||
|
\newcommand\@lstp@def[4]{%
|
||||||
|
#2#3{}%
|
||||||
|
\@for\lstp@def@temp:=#4\do{%
|
||||||
|
\expandafter\SnocTo\expandafter{\lstp@def@temp}#3%
|
||||||
|
}%
|
||||||
|
#1\let#3#3%
|
||||||
|
\let\lstp@def@temp\@undefined
|
||||||
|
}
|
||||||
|
\newtoks\lstp@ta
|
||||||
|
\newtoks\lstp@tb
|
||||||
|
\newcommand\ConsTo{\@lstp@ConsTo\relax\def}
|
||||||
|
\newcommand\gConsTo{\@lstp@ConsTo\global\def}
|
||||||
|
\newcommand\eConsTo{\@lstp@ConsTo\relax\edef}
|
||||||
|
\newcommand\xConsTo{\@lstp@ConsTo\global\edef}
|
||||||
|
\newcommand\@lstp@ConsTo[4]{%
|
||||||
|
\long#2\lstp@temp{#3}%
|
||||||
|
\lstp@ta=\expandafter{\expandafter\listitem\expandafter{\lstp@temp}}%
|
||||||
|
\lstp@tb=\expandafter{#4}%
|
||||||
|
#1\edef#4{\the\lstp@ta\the\lstp@tb}%
|
||||||
|
}
|
||||||
|
\newcommand\SnocTo{\@lstp@SnocTo\relax\def}
|
||||||
|
\newcommand\gSnocTo{\@lstp@SnocTo\global\def}
|
||||||
|
\newcommand\eSnocTo{\@lstp@SnocTo\relax\edef}
|
||||||
|
\newcommand\xSnocTo{\@lstp@SnocTo\global\edef}
|
||||||
|
\newcommand\@lstp@SnocTo[4]{%
|
||||||
|
\long#2\lstp@temp{#3}%
|
||||||
|
\lstp@ta=\expandafter{\expandafter\listitem\expandafter{\lstp@temp}}%
|
||||||
|
\lstp@tb=\expandafter{#4}%
|
||||||
|
#1\edef#4{\the\lstp@tb\the\lstp@ta}%
|
||||||
|
}
|
||||||
|
\newcommand\AppendTo{\@lstp@AppendTo\relax}
|
||||||
|
\newcommand\gAppendTo{\@lstp@AppendTo\global}
|
||||||
|
\newcommand\@lstp@AppendTo[3]{%
|
||||||
|
\lstp@ta=\expandafter{#2}%
|
||||||
|
\lstp@tb=\expandafter{#3}%
|
||||||
|
#1\edef#3{\the\lstp@ta\the\lstp@tb}%
|
||||||
|
}
|
||||||
|
\long\def\@LopOff\listitem#1#2\@LopOff#3#4{%
|
||||||
|
#3{#1}%
|
||||||
|
#4{#2}%
|
||||||
|
}
|
||||||
|
\newcommand\@lstp@LopTo[4]{\expandafter\@LopOff#3\@LopOff{#1\def#4}{#2\def#3}}
|
||||||
|
\newcommand\@lstp@RestTo[3]{\expandafter\@LopOff#2\@LopOff{\@gobble}{#1\def#3}}
|
||||||
|
\newcommand\LopTo{\@lstp@LopTo\relax\relax}
|
||||||
|
\newcommand\gLopTo{\@lstp@LopTo\global\global}
|
||||||
|
\newcommand\glLopTo{\@lstp@LopTo\global\relax}
|
||||||
|
\newcommand\lgLopTo{\@lstp@LopTo\relax\global}
|
||||||
|
\newcommand\FirstTo{\@lstp@LopTo\relax\@gobblethree}
|
||||||
|
\newcommand\gFirstTo{\@lstp@LopTo\global\@gobblethree}
|
||||||
|
\newcommand\RestTo{\@lstp@RestTo\relax}
|
||||||
|
\newcommand\gRestTo{\@lstp@RestTo\global}
|
||||||
|
\newcommand*\IfList[1]{%
|
||||||
|
{%
|
||||||
|
\expandafter\@IfList#1\@IfList
|
||||||
|
}%
|
||||||
|
}
|
||||||
|
\def\@IfList#1#2\@IfList{%
|
||||||
|
\ifx\listitem#1\relax
|
||||||
|
\aftergroup\@firstoftwo
|
||||||
|
\else
|
||||||
|
\aftergroup\@secondoftwo
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
\def\@forList#1:=#2\do#3{%
|
||||||
|
\long\def\lstp@for@listitem##1{%
|
||||||
|
\long\def#1{##1}%
|
||||||
|
#3%
|
||||||
|
\let\listitem\lstp@for@listitem%
|
||||||
|
}%
|
||||||
|
\let\listitem\lstp@for@listitem%
|
||||||
|
#2%
|
||||||
|
\let\listitem\@undefined%
|
||||||
|
}
|
||||||
|
\newcommand\SetToListLength[2]{%
|
||||||
|
\lstp@length{#2}{\value{#1}}%
|
||||||
|
}
|
||||||
|
\newcommand\lstp@length[2]{%
|
||||||
|
#2=0 %
|
||||||
|
\long\def\listitem##1{\advance#2 by1 }%
|
||||||
|
#1\let\listitem\@undefined%
|
||||||
|
}
|
||||||
|
\newcommand\MapListTo{\@lstp@MapListTo\relax}
|
||||||
|
\newcommand\gMapListTo{\@lstp@MapListTo\global}
|
||||||
|
\newcommand\MapAndAppendTo{\@lstp@MapAndAppendTo\relax}
|
||||||
|
\newcommand\gMapAndAppendTo{\@lstp@MapAndAppendTo\global}
|
||||||
|
\newcommand\@lstp@MapListTo[4]{%
|
||||||
|
\let\lstp@map@temp#3%
|
||||||
|
#1\let#4\empty%
|
||||||
|
\@lstp@MapAndAppendTo{#1}{#2}\lstp@map@temp#4%
|
||||||
|
\let\lstp@map@temp\@undefined%
|
||||||
|
}
|
||||||
|
\newcommand\@lstp@MapAndAppendTo[4]{%
|
||||||
|
\long\def\listitem##1{\@lstp@SnocTo{#1}\def{#2}{#4}}%
|
||||||
|
#3%
|
||||||
|
\let\listitem\@undefined%
|
||||||
|
}
|
||||||
|
\newcommand\lstp@insert[3]{%
|
||||||
|
\edef\lstp@insert@temp@a{#2{#1}}%
|
||||||
|
\let\lstp@insert@temp@i#3%
|
||||||
|
\let#3\empty
|
||||||
|
\long\def\lstp@insert@listitem##1{%
|
||||||
|
\edef\lstp@insert@temp@b{#2{##1}}%
|
||||||
|
\ifnum\lstp@insert@temp@a<\lstp@insert@temp@b
|
||||||
|
\SnocTo{#1}{#3}%
|
||||||
|
\let\listitem\lstp@insert@listitem@done
|
||||||
|
\else
|
||||||
|
\let\listitem\lstp@insert@listitem
|
||||||
|
\fi
|
||||||
|
\SnocTo{##1}{#3}%
|
||||||
|
}%
|
||||||
|
\long\def\lstp@insert@listitem@done##1{\SnocTo{##1}{#3}}%
|
||||||
|
\let\listitem\lstp@insert@listitem
|
||||||
|
\lstp@insert@temp@i%
|
||||||
|
\ifx\listitem\lstp@insert@listitem%
|
||||||
|
\SnocTo{#1}{#3}%
|
||||||
|
\fi%
|
||||||
|
\let\lstp@insert@temp@i\@undefined%
|
||||||
|
\let\listitem\@undefined%
|
||||||
|
}
|
||||||
|
\providecommand\@apply@group[2]{#1#2}
|
||||||
|
\newcommand\SortList[2][\@apply@group{}]{%
|
||||||
|
\let\lstp@sort@temp@i#2%
|
||||||
|
\let#2\empty
|
||||||
|
\long\def\lstp@sort@listitem##1{%
|
||||||
|
\lstp@insert{##1}{#1}{#2}%
|
||||||
|
\let\listitem\lstp@sort@listitem
|
||||||
|
}%
|
||||||
|
\let\listitem\lstp@sort@listitem
|
||||||
|
\lstp@sort@temp@i
|
||||||
|
\let\lstp@sort@temp@i\@undefined
|
||||||
|
\let\listitem\@undefined
|
||||||
|
}
|
||||||
|
\newcounter{lstp@ifsucc}
|
||||||
|
\newcommand\lstp@ifsucc[2]{%
|
||||||
|
\setcounter{lstp@ifsucc}{#1}%
|
||||||
|
\addtocounter{lstp@ifsucc}{1}%
|
||||||
|
\ifnum#2=\value{lstp@ifsucc}%
|
||||||
|
\let\@lstp@ifsucc@kont\@firstoftwo
|
||||||
|
\else
|
||||||
|
\let\@lstp@ifsucc@kont\@secondoftwo
|
||||||
|
\fi
|
||||||
|
\@lstp@ifsucc@kont
|
||||||
|
}
|
||||||
|
\newcommand\CompressList[2][\@apply@group{}]{%
|
||||||
|
\let\lstp@compress@temp@i#2%
|
||||||
|
\let#2\empty
|
||||||
|
\def\lstp@compress@add@single{%
|
||||||
|
\expandafter\SnocTo\expandafter
|
||||||
|
{\expandafter\@single\expandafter{\lstp@compress@temp@a}}{#2}%
|
||||||
|
}%
|
||||||
|
\def\lstp@compress@add@range{%
|
||||||
|
\expandafter\expandafter\expandafter\SnocTo
|
||||||
|
\expandafter\expandafter\expandafter{%
|
||||||
|
\expandafter\expandafter\expandafter\@range
|
||||||
|
\expandafter\expandafter\expandafter{%
|
||||||
|
\expandafter\lstp@compress@temp@a\expandafter}%
|
||||||
|
\expandafter{\lstp@compress@temp@b}}#2%
|
||||||
|
}%
|
||||||
|
\long\def\lstp@compress@listitem@start##1{%
|
||||||
|
\def\lstp@compress@temp@a{##1}%
|
||||||
|
\edef\lstp@compress@temp@a@key{#1{##1}}%
|
||||||
|
\let\listitem\lstp@compress@listitem@single
|
||||||
|
}%
|
||||||
|
\long\def\lstp@compress@listitem@single##1{%
|
||||||
|
\def\lstp@compress@temp@b{##1}%
|
||||||
|
\edef\lstp@compress@temp@b@key{#1{##1}}%
|
||||||
|
\ifnum\lstp@compress@temp@a@key=\lstp@compress@temp@b@key
|
||||||
|
\let\listitem\lstp@compress@listitem@single
|
||||||
|
\else
|
||||||
|
\lstp@ifsucc{\lstp@compress@temp@a@key}{\lstp@compress@temp@b@key}
|
||||||
|
{\let\listitem\lstp@compress@listitem@range}
|
||||||
|
{\lstp@compress@add@single
|
||||||
|
\let\lstp@compress@temp@a\lstp@compress@temp@b
|
||||||
|
\let\lstp@compress@temp@a@key\lstp@compress@temp@b@key
|
||||||
|
\let\listitem\lstp@compress@listitem@single}%
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\long\def\lstp@compress@listitem@range##1{%
|
||||||
|
\def\lstp@compress@temp@c{##1}%
|
||||||
|
\edef\lstp@compress@temp@c@key{#1{##1}}%
|
||||||
|
\ifnum\lstp@compress@temp@b@key=\lstp@compress@temp@c@key
|
||||||
|
\let\listitem\lstp@compress@listitem@range
|
||||||
|
\else
|
||||||
|
\lstp@ifsucc{\lstp@compress@temp@b@key}{\lstp@compress@temp@c@key}
|
||||||
|
{%
|
||||||
|
\let\lstp@compress@temp@b\lstp@compress@temp@c
|
||||||
|
\let\lstp@compress@temp@b@key\lstp@compress@temp@c@key
|
||||||
|
\let\listitem\lstp@compress@listitem@range
|
||||||
|
}
|
||||||
|
{%
|
||||||
|
\lstp@compress@add@range
|
||||||
|
\let\lstp@compress@temp@a\lstp@compress@temp@c
|
||||||
|
\let\lstp@compress@temp@a@key\lstp@compress@temp@c@key
|
||||||
|
\let\listitem\lstp@compress@listitem@single
|
||||||
|
}%
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\let\listitem\lstp@compress@listitem@start
|
||||||
|
\lstp@compress@temp@i
|
||||||
|
\ifx\listitem\lstp@compress@listitem@single
|
||||||
|
\lstp@compress@add@single
|
||||||
|
\else
|
||||||
|
\ifx\listitem\lstp@compress@listitem@range
|
||||||
|
\lstp@compress@add@range
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\let\lstp@compress@temp@a\@undefined
|
||||||
|
\let\lstp@compress@temp@b\@undefined
|
||||||
|
\let\lstp@compress@temp@c\@undefined
|
||||||
|
\let\lstp@compress@temp@a@key\@undefined
|
||||||
|
\let\lstp@compress@temp@b@key\@undefined
|
||||||
|
\let\lstp@compress@temp@c@key\@undefined
|
||||||
|
\let\lstp@compress@temp@i\@undefined
|
||||||
|
\let\listitem\@undefined
|
||||||
|
}
|
||||||
|
\newcommand\FormatListSepTwo{ and }
|
||||||
|
\newcommand\FormatListSepMore{, }
|
||||||
|
\newcommand\FormatListSepLast{, and }
|
||||||
|
\newcounter{lstp@FormatList@length}
|
||||||
|
\newcounter{lstp@FormatList@posn}
|
||||||
|
\newcommand\FormatList[4]{{%
|
||||||
|
\deflist\lstp@FormatList@list{#4}%
|
||||||
|
\SetToListLength{lstp@FormatList@length}\lstp@FormatList@list%
|
||||||
|
\setcounter{lstp@FormatList@posn}{0}%
|
||||||
|
\ifnum\value{lstp@FormatList@length}=1%
|
||||||
|
#1%
|
||||||
|
\else%
|
||||||
|
#2%
|
||||||
|
\fi%
|
||||||
|
\def\listitem##1{%
|
||||||
|
\addtocounter{lstp@FormatList@posn}{1}%
|
||||||
|
\ifnum1<\value{lstp@FormatList@posn}%
|
||||||
|
\ifnum2=\value{lstp@FormatList@length}%
|
||||||
|
\FormatListSepTwo
|
||||||
|
\else
|
||||||
|
\ifnum\value{lstp@FormatList@length}=\value{lstp@FormatList@posn}%
|
||||||
|
\FormatListSepLast
|
||||||
|
\else
|
||||||
|
\FormatListSepMore
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
#3{##1}%
|
||||||
|
}%
|
||||||
|
\lstp@FormatList@list
|
||||||
|
}}
|
||||||
|
\newcommand\ListExpr[1]{\@lstp@ListExpr{#1}\relax}
|
||||||
|
\newcommand\ListExprTo[2]{\@lstp@ListExpr{#1}{\def#2}}
|
||||||
|
\newcommand\gListExprTo[2]{\@lstp@ListExpr{#1}{\gdef#2}}
|
||||||
|
\newcommand\@lstp@defbinop[2]{%
|
||||||
|
\newcommand#1[2]{%
|
||||||
|
\Eval{##1}\let\@lstp@tmp\@lstp@acc
|
||||||
|
{\Eval{##2}}%
|
||||||
|
#2\@lstp@tmp\@lstp@acc
|
||||||
|
}%
|
||||||
|
}
|
||||||
|
\newcommand\@lstp@defunop[2]{%
|
||||||
|
\newcommand#1[1]{%
|
||||||
|
\Eval{##1}%
|
||||||
|
#2\@lstp@acc\@lstp@acc
|
||||||
|
}%
|
||||||
|
}
|
||||||
|
\newcommand\@lstp@definplaceunopopt[3][]{%
|
||||||
|
\newcommand#2[2][#1]{%
|
||||||
|
\Eval{##2}%
|
||||||
|
#3[##1]\@lstp@acc
|
||||||
|
\global\let\@lstp@acc\@lstp@acc
|
||||||
|
}%
|
||||||
|
}
|
||||||
|
\newcommand\@lstp@ListExpr[2]{%
|
||||||
|
{%
|
||||||
|
\gdef\@lstp@acc{}%
|
||||||
|
\def\Eval##1{%
|
||||||
|
\IfList{##1}{%
|
||||||
|
\global\let\@lstp@acc##1%
|
||||||
|
}{%
|
||||||
|
\@lstp@ifListOp##1\@lstp@ifListOp{%
|
||||||
|
##1%
|
||||||
|
}{%
|
||||||
|
\xdef\@lstp@acc{##1}%
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\def\Q##1{\gdef\@lstp@acc{##1}}%
|
||||||
|
\def\Nil{\global\let\@lstp@acc\empty}%
|
||||||
|
\def\List##1{\gdeflist\@lstp@acc{##1}}%
|
||||||
|
\@lstp@defbinop\Cons\xConsTo
|
||||||
|
\@lstp@defbinop\Snoc\xSnocTo
|
||||||
|
\@lstp@defunop\First\gFirstTo
|
||||||
|
\@lstp@defunop\Rest\gRestTo
|
||||||
|
\@lstp@defbinop\Append\gAppendTo
|
||||||
|
\@lstp@definplaceunopopt[\@apply@group{}]\Sort\SortList
|
||||||
|
\@lstp@definplaceunopopt[\@apply@group{}]\Compress\CompressList
|
||||||
|
\newcommand\Map[2]{%
|
||||||
|
\Eval{##2}%
|
||||||
|
\gMapListTo{##1}\@lstp@acc\@lstp@acc
|
||||||
|
}%
|
||||||
|
\Eval{#1}%
|
||||||
|
}%
|
||||||
|
\def\@lstp@finish##1{#2{##1}}%
|
||||||
|
\expandafter\@lstp@finish\expandafter{\@lstp@acc}%
|
||||||
|
}
|
||||||
|
\def\@lstp@ifListOp#1#2\@lstp@ifListOp{%
|
||||||
|
\@lstp@ifInToks#1{
|
||||||
|
\Q\Nil\List\Cons\Snoc\Append
|
||||||
|
\First\Rest\Sort\Compress\Map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\newcommand\@lstp@ifInToks[2]{%
|
||||||
|
{%
|
||||||
|
\def\@tester##1#1##2\@tester{%
|
||||||
|
\ifx\@notfound##2\relax
|
||||||
|
\aftergroup\@secondoftwo
|
||||||
|
\else
|
||||||
|
\aftergroup\@firstoftwo
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\@tester#2\@lstp@ifInToks#1\@notfound\@tester
|
||||||
|
}%
|
||||||
|
}
|
||||||
|
\endinput
|
||||||
|
%%
|
||||||
|
%% End of file `listproc.sty'.
|
|
@ -0,0 +1,328 @@
|
||||||
|
%%
|
||||||
|
%% This is file `ottalt.sty',
|
||||||
|
%% generated with the docstrip utility.
|
||||||
|
%%
|
||||||
|
%% The original source files were:
|
||||||
|
%%
|
||||||
|
%% ottalt.dtx (with options: `package')
|
||||||
|
%%
|
||||||
|
%% Copyright (C) 2011 by Jesse A. Tov
|
||||||
|
%%
|
||||||
|
%% This file may be distributed and/or modified under the conditions of the
|
||||||
|
%% LaTeX Project Public License, either version 1.2 of this license or (at
|
||||||
|
%% your option) any later version. The latest version of this license is
|
||||||
|
%% in:
|
||||||
|
%%
|
||||||
|
%% http://www.latex-project.org/lppl.txt
|
||||||
|
%%
|
||||||
|
%% and version 1.2 or later is part of all distributions of LaTeX
|
||||||
|
%% version 1999/12/01 or later.
|
||||||
|
%%
|
||||||
|
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
|
||||||
|
\ProvidesPackage{ottalt}
|
||||||
|
[2013/03/14 v0.11 alternate Ott layout style]
|
||||||
|
\RequirePackage{mathpartir}
|
||||||
|
\RequirePackage{ifthen}
|
||||||
|
\RequirePackage{keyval}
|
||||||
|
\RequirePackage{listproc}
|
||||||
|
\DeclareOption{implicitPremiseBreaks}{
|
||||||
|
\renewcommand\ottaltpremisesep{\\}
|
||||||
|
\renewcommand\ottaltpremisebreak{\\}
|
||||||
|
}
|
||||||
|
\DeclareOption{lineBreakHack}{
|
||||||
|
\renewcommand\ottaltpremisesep{\mpr@andcr}
|
||||||
|
\renewcommand\ottaltpremisebreak{\\\\}
|
||||||
|
}
|
||||||
|
\DeclareOption{implicitLineBreakHack}{
|
||||||
|
\renewcommand\ottaltpremisesep{\\}
|
||||||
|
\renewcommand\ottaltpremisebreak{\\\\}
|
||||||
|
}
|
||||||
|
\DeclareOption{alternateNonterms}{
|
||||||
|
\let\ifnotalternateNonterms\@secondoftwo
|
||||||
|
}
|
||||||
|
\DeclareOption{supertabular}{
|
||||||
|
\ottalt@supertabulartrue
|
||||||
|
}
|
||||||
|
\newcommand\ottaltpremisesep{\\}
|
||||||
|
\newcommand\ottaltpremisebreak{\\}
|
||||||
|
\let\ifnotalternateNonterms\@firstoftwo
|
||||||
|
\newif\ifottalt@supertabular
|
||||||
|
\ProcessOptions
|
||||||
|
\ifottalt@supertabular
|
||||||
|
\RequirePackage{supertabular}
|
||||||
|
\fi
|
||||||
|
\newcommand\inputott[2][ott]{
|
||||||
|
\input{#2}
|
||||||
|
\renewottcommands[#1]
|
||||||
|
}
|
||||||
|
\newcommand\ottaltcurrentprefix{ott}
|
||||||
|
\newcommand\renewottcommands[1][ott]{
|
||||||
|
\renewcommand\ottaltcurrentprefix{#1}
|
||||||
|
\def\renewottcomm@nd##1{
|
||||||
|
\expandafter\renewcommand\csname #1##1\endcsname
|
||||||
|
}
|
||||||
|
\renewottcomm@nd{drule}[4][]{
|
||||||
|
\def\ottalt@nextpremise{}
|
||||||
|
\ottalt@premisetoks={ }
|
||||||
|
##2
|
||||||
|
\expandafter\ottalt@inferrule\expandafter
|
||||||
|
{\the\ottalt@premisetoks}{##3}{##4}{##1}
|
||||||
|
}
|
||||||
|
\renewottcomm@nd{premise}[1]{%
|
||||||
|
\ottalt@premisetoks=
|
||||||
|
\expandafter\expandafter\expandafter
|
||||||
|
{\expandafter\the\expandafter\ottalt@premisetoks
|
||||||
|
\ottalt@nextpremise##1}
|
||||||
|
\ottalt@iflinebreakhack##1\ottlinebreakhack\ottalt@iflinebreakhack{
|
||||||
|
\let\ottalt@nextpremise\ottaltpremisebreak
|
||||||
|
}{
|
||||||
|
\let\ottalt@nextpremise\ottaltpremisesep
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\renewottcomm@nd{usedrule}[1]{%
|
||||||
|
\ifottalt@firstrule
|
||||||
|
\ottalt@firstrulefalse
|
||||||
|
\else
|
||||||
|
%\and
|
||||||
|
%% sigart.cls uses \and for the title and mangles it horribly
|
||||||
|
%% so we cannot use it here. Instead, we drop down to what
|
||||||
|
%% mathpartir wants to redefine the \and command to be anyways
|
||||||
|
\mpr@andcr
|
||||||
|
%%\quad
|
||||||
|
\fi
|
||||||
|
\ensuremath{##1}
|
||||||
|
}
|
||||||
|
\renewenvironment{#1defnblock}[3][]
|
||||||
|
{\begin{drulepar}{##2}{##3}}
|
||||||
|
{\end{drulepar}}
|
||||||
|
\renewottcomm@nd{drulename}[1]{%
|
||||||
|
\ottalt@replace@cs\ranchor\_-{}##1\\
|
||||||
|
}
|
||||||
|
\renewottcomm@nd{prodline}[6]{
|
||||||
|
\ifthenelse{\equal{##3}{}}{
|
||||||
|
\\ & & $##1$ & $##2$ & & $##5$ & $##6$
|
||||||
|
}{}
|
||||||
|
}
|
||||||
|
\renewottcomm@nd{prodnewline}{\relax}
|
||||||
|
\renewottcomm@nd{grammartabular}[1]{%
|
||||||
|
\begin{ottaltgrammar}##1\end{ottaltgrammar}%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\newcommand*\drule@h@lper[3]{%
|
||||||
|
\expandafter\ifx\csname\ottaltcurrentprefix drule#3\endcsname\relax
|
||||||
|
\PackageWarning{ottalt}{Unknown ott rule: #3}%
|
||||||
|
\mbox{\textbf{(#2?)}}%
|
||||||
|
\else
|
||||||
|
\csname\ottaltcurrentprefix usedrule\endcsname
|
||||||
|
{\csname\ottaltcurrentprefix drule#3\endcsname{#1}}%
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
\newcommand*\nonterm@h@lper[1]{\csname\ottaltcurrentprefix#1\endcsname}
|
||||||
|
\newcommand\rrefruletext{rule}
|
||||||
|
\newcommand\Rrefruletext{\expandafter\MakeUppercase\rrefruletext}
|
||||||
|
\newcommand\rrefrulestext{\rrefruletext s}
|
||||||
|
\newcommand\Rrefrulestext{\Rrefruletext s}
|
||||||
|
\newcommand\rrefstyle{\normalfont\scshape}
|
||||||
|
\newcommand\ranchorstyle{\rrefstyle}
|
||||||
|
\providecommand\wraparoundrref{\relax}
|
||||||
|
\newcommand*\rref{%
|
||||||
|
\@ifnextchar*
|
||||||
|
{\rref@star}
|
||||||
|
{\rref@with\rrefruletext\rrefrulestext}}
|
||||||
|
\newcommand*\Rref{%
|
||||||
|
\@ifnextchar*
|
||||||
|
{\rref@star}
|
||||||
|
{\rref@with\Rrefruletext\Rrefrulestext}}
|
||||||
|
\newcommand*\rref@with[2]{\FormatList{#1~}{#2~}{\one@rref}}
|
||||||
|
\newcommand*\rref@star[1]{\FormatList{}{}{\one@rref}}
|
||||||
|
\newcommand*\@one@rref@nohyper[1]{\wraparoundrref{{\rrefstyle{#1}}}}
|
||||||
|
\newcommand*\@ranchor@nohyper[1]{{\ranchorstyle{#1}}}
|
||||||
|
\AtBeginDocument{
|
||||||
|
\ifcsname hypertarget\endcsname
|
||||||
|
\newcommand*\one@rref[1]{%
|
||||||
|
\hyperlink
|
||||||
|
{ottalt:rule:\ottaltcurrentprefix:#1}
|
||||||
|
{\@one@rref@nohyper{#1}}%
|
||||||
|
}
|
||||||
|
\newcommand*\ranchor[1]{%
|
||||||
|
\hypertarget
|
||||||
|
{ottalt:rule:\ottaltcurrentprefix:#1}
|
||||||
|
{\@ranchor@nohyper{#1}}%
|
||||||
|
}
|
||||||
|
\else
|
||||||
|
\newcommand\one@rref{\@one@rref@nohyper}
|
||||||
|
\newcommand\ranchor{\@ranchor@nohyper}
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
\newcommand*{\drules}[4][\relax]{%
|
||||||
|
\begin{drulepar}[#1]{#2}{#3}
|
||||||
|
\@for\@ottalt@each:=#4\do{%
|
||||||
|
\expandafter\drule\expandafter{\@ottalt@each}
|
||||||
|
}
|
||||||
|
\end{drulepar}%
|
||||||
|
}
|
||||||
|
\newenvironment{drulepar}[3][\relax]
|
||||||
|
{\begin{rulesection}[#1]{#2}{#3}%
|
||||||
|
\begin{mathparpagebreakable}}
|
||||||
|
{\end{mathparpagebreakable}%
|
||||||
|
\end{rulesection}}
|
||||||
|
\newenvironment{drulepar*}[3][\relax]
|
||||||
|
{\begin{rulesection*}[#1]{#2}{#3}%
|
||||||
|
\begin{mathparpagebreakable}}
|
||||||
|
{\end{mathparpagebreakable}%
|
||||||
|
\end{rulesection*}}
|
||||||
|
\newenvironment{rulesection}[3][\relax]
|
||||||
|
{\trivlist\item
|
||||||
|
\ifx#1\relax\else\def\ottalt@rulesection@prefix{#1-}\fi
|
||||||
|
\drulesectionhead{#2}{#3}%
|
||||||
|
\nopagebreak[4]%
|
||||||
|
\noindent}
|
||||||
|
{\endtrivlist}
|
||||||
|
\newenvironment{rulesection*}[3][\relax]
|
||||||
|
{\trivlist\item
|
||||||
|
\ifx#1\relax\else\def\ottalt@rulesection@prefix{#1-}\fi
|
||||||
|
\drulesectionhead*{#2}{#3}%
|
||||||
|
\nopagebreak[4]%
|
||||||
|
\noindent}
|
||||||
|
{\endtrivlist}
|
||||||
|
\newcommand\ottalt@rulesection@prefix{}
|
||||||
|
\newcommand*{\drulesectionhead}{%
|
||||||
|
\@ifnextchar *{\drulesectionheadMany}{\drulesectionheadOne}%
|
||||||
|
}
|
||||||
|
\newcommand*{\drulesectionheadOne}[2]{%
|
||||||
|
\FormatDruleSectionHead{#1}%
|
||||||
|
\hfill\FormatDruleSectionHeadRight{#2}%
|
||||||
|
\par
|
||||||
|
}
|
||||||
|
\newcommand*{\drulesectionheadMany}[3]{%
|
||||||
|
{%
|
||||||
|
\let\FormatListSepTwo\FormatDruleSepTwo
|
||||||
|
\let\FormatListSepMore\FormatDruleSepMore
|
||||||
|
\let\FormatListSepLast\FormatDruleSepLast
|
||||||
|
\FormatList{}{}{\FormatDruleSectionHeads}{#2}%
|
||||||
|
}%
|
||||||
|
\hfill\FormatDruleSectionHeadRight{#3}%
|
||||||
|
\par
|
||||||
|
}
|
||||||
|
\newcommand*\FormatDruleSepTwo{\,,~}
|
||||||
|
\newcommand*\FormatDruleSepMore{\FormatDruleSepTwo}
|
||||||
|
\newcommand*\FormatDruleSepLast{\FormatDruleSepTwo}
|
||||||
|
\newcommand*\FormatDruleSectionHead[1]{\fbox{#1}}
|
||||||
|
\newcommand*\FormatDruleSectionHeads[1]{\fbox{\strut#1}}
|
||||||
|
\newcommand*\FormatDruleSectionHeadRight[1]{\emph{#1}}
|
||||||
|
\newcommand*\drule[2][]{%
|
||||||
|
\expandafter\drule@helper\expandafter{\ottalt@rulesection@prefix}{#1}{#2}%
|
||||||
|
}
|
||||||
|
\newcommand*\drule@helper[3]{%
|
||||||
|
\ottalt@replace@cs{\drule@h@lper{#2}{#1#3}}-{XX}{}#1#3\\
|
||||||
|
}
|
||||||
|
\newcommand\ottaltinferrule[4]{
|
||||||
|
\inferrule*[narrower=0.3,lab=#1,#2]
|
||||||
|
{#3}
|
||||||
|
{#4}
|
||||||
|
}
|
||||||
|
\newcommand\ottalt@inferrule[4]{
|
||||||
|
\ottaltinferrule{#3}{#4}{#1}{#2}
|
||||||
|
}
|
||||||
|
\newif\ifottalt@firstrule \ottalt@firstruletrue
|
||||||
|
\newcommand{\ottalt@nextpremise}{\relax}
|
||||||
|
\newtoks\ottalt@premisetoks
|
||||||
|
\newcommand{\ottlinebreakhack}{\relax}
|
||||||
|
\def\ottalt@iflinebreakhack#1\ottlinebreakhack #2\ottalt@iflinebreakhack{%
|
||||||
|
\ifthenelse{\equal{#2}{}}\@secondoftwo\@firstoftwo
|
||||||
|
}
|
||||||
|
\newcommand\ottalt@replace@cs[5]{%
|
||||||
|
\ifx\\#5\relax
|
||||||
|
\def\ottalt@replace@cs@kont{#1{#4}}%
|
||||||
|
\else
|
||||||
|
\ifx#2#5\relax
|
||||||
|
\def\ottalt@replace@cs@kont{\ottalt@replace@cs{#1}{#2}{#3}{#4#3}}%
|
||||||
|
\else
|
||||||
|
\def\ottalt@replace@cs@kont{\ottalt@replace@cs{#1}{#2}{#3}{#4#5}}%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\ottalt@replace@cs@kont
|
||||||
|
}
|
||||||
|
\newcommand*\nonterms[2][8pt]{
|
||||||
|
\begin{ottaltgrammar}[#1]
|
||||||
|
\@for\@ottalt@each:=#2\do{%
|
||||||
|
\expandafter\nt\expandafter{\@ottalt@each}
|
||||||
|
}
|
||||||
|
\end{ottaltgrammar}
|
||||||
|
}
|
||||||
|
\newenvironment{ottaltgrammar}[1][8pt]{%
|
||||||
|
\begingroup
|
||||||
|
\trivlist\item
|
||||||
|
\def\OTTALTNEWLINE{\\[#1]}%
|
||||||
|
\def\nt##1{\OTTALTNEWLINE\relax\nonterm@h@lper{##1}\ignorespaces}%
|
||||||
|
\newcommand\ottaltintertext[2]{%
|
||||||
|
\multicolumn{8}{l}{%
|
||||||
|
\begin{minipage}{##1}%
|
||||||
|
##2%
|
||||||
|
\end{minipage}%
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\ifottalt@supertabular
|
||||||
|
\begin{supertabular}{llcllllll}
|
||||||
|
\else
|
||||||
|
\begin{tabular}{llcllllll}
|
||||||
|
\fi
|
||||||
|
\let\OTTALTNEWLINE\relax
|
||||||
|
\ignorespaces
|
||||||
|
}
|
||||||
|
{%
|
||||||
|
\@ifundefined{ottafterlastrule}{\\}{\ottafterlastrule}%
|
||||||
|
\ifottalt@supertabular
|
||||||
|
\end{supertabular}
|
||||||
|
\else
|
||||||
|
\end{tabular}
|
||||||
|
\fi
|
||||||
|
\endtrivlist
|
||||||
|
\endgroup
|
||||||
|
\ignorespaces
|
||||||
|
}
|
||||||
|
\newcommand\newNTclass[2][\ifnotalternateNonterms]{
|
||||||
|
\expandafter\newcommand\csname new#2s\endcsname[4][]{
|
||||||
|
#1{
|
||||||
|
\expandafter\newcommand\csname ottalt@NT@#2@##2\endcsname{##1{##3}}
|
||||||
|
}{
|
||||||
|
\expandafter\newcommand\csname ottalt@NT@#2@##2\endcsname{##4}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\expandafter\newcommand\csname new#2\endcsname[3][]{
|
||||||
|
\csname new#2s\endcsname[##1]{##2}{##3}{##3}
|
||||||
|
}
|
||||||
|
\expandafter\newcommand\csname #2\endcsname[1]{%
|
||||||
|
\csname ottalt@NT@#2@##1\endcsname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\providecommand\@ifToif[1]{%
|
||||||
|
#1\iftrue\iffalse
|
||||||
|
}
|
||||||
|
\providecommand\ifTo@if[1]{%
|
||||||
|
#1%
|
||||||
|
\expandafter\@firstoftwo
|
||||||
|
\else
|
||||||
|
\expandafter\@secondoftwo
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
\newcommand\NTOVERLINE{\NTCAPTURE\overline}
|
||||||
|
\newcommand\NTUNDERLINE{\NTCAPTURE\underline}
|
||||||
|
\newcommand\NTTEXTCOLOR[1]{\NTCAPTURE{\textcolor{#1}}}
|
||||||
|
\newcommand\NTCAPTURE[1]{\NTCAPTURELOW{\NTCAPTURE@FINISH{#1}}}
|
||||||
|
\newcommand\NTCAPTURE@FINISH[4]{#1{#2_{#3}#4}}
|
||||||
|
\newcommand\NTCAPTURELOW[2]{\NT@CAPTURE@LOOP{#1}{#2}\relax\relax}
|
||||||
|
\newcommand\NT@CAPTURE@LOOP[4]{%
|
||||||
|
\@ifnextchar _{%
|
||||||
|
\NT@CAPTURE@SUB{#1}{#2}{#3}{#4}%
|
||||||
|
}{\@ifnextchar '{%
|
||||||
|
\NT@CAPTURE@PRIME{#1}{#2}{#3}{#4}%
|
||||||
|
}{%
|
||||||
|
{#1{#2}{#3}{#4}}%
|
||||||
|
}}%
|
||||||
|
}
|
||||||
|
\def\NT@CAPTURE@SUB#1#2#3#4_#5{\NT@CAPTURE@LOOP{#1}{#2}{#3#5}{#4}}
|
||||||
|
\def\NT@CAPTURE@PRIME#1#2#3#4'{\NT@CAPTURE@LOOP{#1}{#2}{#3}{#4'}}
|
||||||
|
\endinput
|
||||||
|
%%
|
||||||
|
%% End of file `ottalt.sty'.
|
Loading…
Reference in New Issue