Finished Discussion
This commit is contained in:
parent
f9a4db5a53
commit
5d4df59b92
41
cbpv.bib
41
cbpv.bib
|
@ -0,0 +1,41 @@
|
|||
@inproceedings{cbpv,
|
||||
author = {Forster, Yannick and Sch\"{a}fer, Steven and Spies, Simon and Stark, Kathrin},
|
||||
title = {{Call-by-push-value in Coq: operational, equational, and denotational theory}},
|
||||
year = 2019,
|
||||
isbn = {9781450362221},
|
||||
publisher = {Association for Computing Machinery},
|
||||
address = {New York, NY, USA},
|
||||
doi = {10.1145/3293880.3294097},
|
||||
booktitle = {Proceedings of the 8th ACM SIGPLAN International Conference on Certified Programs and Proofs},
|
||||
pages = {118--131},
|
||||
numpages = {14},
|
||||
location = {Cascais, Portugal},
|
||||
series = {CPP 2019}
|
||||
}
|
||||
|
||||
@article{poplmark,
|
||||
title = {{POPLMark reloaded: Mechanizing proofs by logical relations}},
|
||||
volume = 29,
|
||||
DOI = {10.1017/S0956796819000170},
|
||||
journal = {Journal of Functional Programming},
|
||||
publisher = {Cambridge University Press},
|
||||
author = {Abel, Andreas and Allais, Guillaume and Hameer, Aliya and Pientka, Brigitte and Momigliano, Alberto and Schäfer, Steven and Stark, Kathrin},
|
||||
year = 2019,
|
||||
pages = {e19}
|
||||
}
|
||||
|
||||
@inproceedings{autosubst2,
|
||||
author = {Stark, Kathrin and Sch\"{a}fer, Steven and Kaiser, Jonas},
|
||||
title = {{Autosubst 2: reasoning with multi-sorted de Bruijn terms and vector substitutions}},
|
||||
year = 2019,
|
||||
isbn = {9781450362221},
|
||||
publisher = {Association for Computing Machinery},
|
||||
address = {New York, NY, USA},
|
||||
doi = {10.1145/3293880.3294101},
|
||||
booktitle = {Proceedings of the 8th ACM SIGPLAN International Conference on Certified Programs and Proofs},
|
||||
pages = {166--180},
|
||||
numpages = 15,
|
||||
keywords = {de Bruijn repersentation, multi-sorted terms, parallel substiutions, sigma-calculus},
|
||||
location = {Cascais, Portugal},
|
||||
series = {CPP 2019}
|
||||
}
|
136
cbpv.mng
136
cbpv.mng
|
@ -3,13 +3,14 @@
|
|||
\usepackage[supertabular]{ottalt}
|
||||
\let\newlist\relax
|
||||
\let\renewlist\relax
|
||||
\usepackage[margin=1in]{geometry}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{mlmodern}
|
||||
\usepackage[margin=1in]{geometry}
|
||||
\usepackage{enumitem,float,booktabs,xspace,doi}
|
||||
\usepackage{enumitem,float,booktabs,xspace,xcolor,doi}
|
||||
\usepackage{amsmath,amsthm,amssymb}
|
||||
\usepackage[capitalize,nameinlink,noabbrev]{cleveref}
|
||||
\usepackage{mathpartir,mathtools,stmaryrd,latexsym}
|
||||
\usepackage[capitalize,nameinlink,noabbrev]{cleveref}
|
||||
\usepackage[numbers]{natbib}
|
||||
|
||||
\setlist{noitemsep}
|
||||
\hypersetup{
|
||||
|
@ -43,8 +44,8 @@
|
|||
\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).
|
||||
It follows work by Forster, Sch\"afer, Spies, and Stark \citep{cbpv} on mechanizing the metatheory of CBPV in Rocq,
|
||||
but instead adapts the proof technique from POPLMark Reloaded \citep{poplmark}.
|
||||
|
||||
Both proofs, and mine, follow the same sequence of steps:
|
||||
we define a logical relation that semantically interpret types as sets of terms,
|
||||
|
@ -60,7 +61,8 @@ 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),
|
||||
I have implemented a mutual induction tactic for Lean%
|
||||
\footnote{\url{https://github.com/ionathanch/MutualInduction}},
|
||||
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.
|
||||
|
@ -301,7 +303,7 @@ 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{} \\
|
||||
\fbox{$[[v ∈ ⟦A⟧]]$} \quad \fbox{$[[m ∈ ⟦B⟧]]$} \hfill \textit{semantic inhabitance of types} \\
|
||||
\begin{mathpar}
|
||||
\drule[]{LRPP-Unit-var}
|
||||
\drule[]{LRPP-Unit-unit}
|
||||
|
@ -716,6 +718,8 @@ traditional strong normalization of well typed terms holds as a corollary.
|
|||
|
||||
\section{Discussion} \label{sec:discussion}
|
||||
|
||||
\subsection{Proof Structure of Strong Normalization}
|
||||
|
||||
Overall, the inductive characterization of strongly normal terms is convenient to work with.
|
||||
Its congruence and inversion properties are exactly what are needed
|
||||
to show \nameref{lem:closure} and \nameref{lem:adequacy} of the logical relation,
|
||||
|
@ -797,4 +801,122 @@ to the particularities of the chosen reduction strategy.
|
|||
|
||||
\subsection{Lean for PL Metatheory}
|
||||
|
||||
The proof development involved in this report consists of nine files,
|
||||
as mentioned throughout.
|
||||
\Cref{tab:loc} gives the number of non-blank, non-comment lines of code for each file,
|
||||
which roughly reflects the amount of proof effort I required.
|
||||
The \texttt{Syntax.lean} file involves a lot of renaming and substitution proofs,
|
||||
but I copied these from prior proof developments with minimal changes to adapt them to CBPV.
|
||||
The actual semantic proofs in \texttt{NormalInd.lean}, \texttt{OpenSemantics.lean}, and \texttt{Soundness.lean}
|
||||
took roughly equal amounts of time to complete.
|
||||
As said in \cref{sec:sn-acc}, the proofs in \texttt{NormalAcc.lean}
|
||||
along with its dependency on \texttt{Reduction.lean} took nearly as much time to complete
|
||||
as the rest of the semantic proofs,
|
||||
while \texttt{LeftmostOutermost.lean} mostly mirrors \texttt{Reduction.lean}.
|
||||
The entire project, excluding this report, took about a week to complete.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{lr}
|
||||
\toprule
|
||||
File & LOC \\
|
||||
\midrule
|
||||
\texttt{Syntax.lean} & 252 \\
|
||||
\texttt{Typing.lean} & 48 \\
|
||||
\texttt{NormalInd.lean} & 192 \\
|
||||
\texttt{OpenSemantics.lean} & 107 \\
|
||||
\texttt{Soundness.lean} & 114 \\
|
||||
\texttt{Normalization.lean} & 48 \\
|
||||
\texttt{Reduction.lean} & 187 \\
|
||||
\texttt{NormalAcc.lean} & 291 \\
|
||||
\texttt{LeftmostOutermost.lean} & 276 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{Lean development files and lines of code}
|
||||
\label{tab:loc}
|
||||
\end{table}
|
||||
|
||||
One of the main technical challenges in mechanizing CBPV in Lean is dealing with mutual induction.
|
||||
While Lean currently supports mutually defined inductive types,
|
||||
the options for eliminating them are somewhat buggy and restricted.
|
||||
At the lower level,
|
||||
Lean generates independent eliminators (which they call \emph{recursors})
|
||||
for each of the mutual inductives,
|
||||
each with motives for all mutual inductives,
|
||||
similar to what \texttt{Scheme Induction for ... with Induction for ...}
|
||||
generates in Rocq.
|
||||
|
||||
Lean's induction tactic produces applications of the appropriate recursor,
|
||||
but does not support mutual inductives.
|
||||
In cases where induction on only a single inductive from the mutual definitions is needed,
|
||||
the induction tactic can be supplied with a custom recursor,
|
||||
in this case the appropriate inductive's recursor with all other motives
|
||||
instantiated to trivial propositions.
|
||||
Unfortunately, this fails because the tactic cannot handle induction cases
|
||||
with different numbers of indices in the inductive type,
|
||||
even if those other cases are eventually trivial.
|
||||
|
||||
Lean supports structural recursion on mutual inductives,
|
||||
which is implemented via a recursor on an auxiliary inductive
|
||||
that enables strong induction.
|
||||
However, this feature is currently a little buggy,
|
||||
and fails on some more complex inductive types.%
|
||||
\footnote{\url{https://github.com/leanprover/lean4/issues/1672}}
|
||||
Futhermore, writing proofs as recursive functions is unconventional,
|
||||
and isn't amenable to even simple automation that can automatically apply induction hypotheses.
|
||||
|
||||
Of course, it's possible to manually apply the recursors that Lean generates for each mutual inductive.
|
||||
This is inconvenient for several reasons:
|
||||
motives need to be explicitly specified, even when they're inferrable from the goals;
|
||||
cases with trivial motives still need to be explicitly proven;
|
||||
and induction cases are duplicated across the recursors.
|
||||
A partial solution, especially for the last inconvenience,
|
||||
is to generate the same kind of combined recursor that \texttt{Combined Scheme ...}
|
||||
does for Rocq, but it still requires explicit application.
|
||||
The mutual induction tactic I had implemented (outside of this project)
|
||||
aims to solve these issues.
|
||||
|
||||
In short, my mutual induction tactic targets multiple goals at a time.
|
||||
Applying the tactic on targets in mutually defined inductives from different goals
|
||||
applies their respective recursors, inferring motives from those goals,
|
||||
but deduplicates the induction cases, and introduces these cases as new subgoals.
|
||||
If a target and goal for a particular inductive is missing,
|
||||
the motive for that inductive is set as a trivially inhabited type,
|
||||
and all cases for that motive are automatically solved.
|
||||
|
||||
The mutual induction tactic has worked very well for this project.
|
||||
The mutual inductives involved are the value and computation terms and types (2 and 2),
|
||||
their typing judgements (2), the logical relation (2),
|
||||
the small-step reduction relation (2),
|
||||
and the mutually inductive definition of strongly neutral and normal terms and head reduction (4).
|
||||
The tactic was used for every proof by mutual induction mentioned here.
|
||||
Additionally, it was used twice for single induction
|
||||
(\ie all other motives are trivial): \rref{SN-Force-inv} and \nameref{cor:ext}.
|
||||
|
||||
Because the mutual induction tactic is merely a tactic and not a top-level construct,
|
||||
some amount of manipulation is still required to massage the proof state
|
||||
into one where the tactic can be used.
|
||||
Specifically, mutual theorems are first stated as some conjunction
|
||||
$(\forall v, P \gap v) \wedge (\forall m, Q \gap m)$,
|
||||
then split into two separate goals with targets $v, m$ introduced into the context,
|
||||
before mutual induction is applied to $v$ and $m$ with inferred motives $P$ and $Q$.
|
||||
This means that using the theorems individually requires projecting from the conjunction.
|
||||
There are discussions underway for introducing top-level syntax for mutual theorems,
|
||||
similar to Rocq's \texttt{Theorem ... with ...} vernacular,
|
||||
so that multiple goals are introduced automatically with their hypotheses.%
|
||||
\footnote{\url{https://leanprover.zulipchat.com/\#narrow/channel/239415-metaprogramming-.2F-tactics/topic/mutual.20induction.20tactic/near/504421657}}
|
||||
|
||||
Aside from mutual induction,
|
||||
the other technical challenge is proving all the renaming and substitution lemmas.
|
||||
There is no library like Autosubst 2 \citep{autosubst2} to automate defining and proving these lemmas.
|
||||
In multiple places, substitutions need to be massaged into different propositionally equal forms,
|
||||
and this massaging requires knowing exactly what equality is needed.
|
||||
For PL metatheory that doesn't involve mutual definitions
|
||||
but does involve some notion of binding and abstraction,
|
||||
the lack of a library for substitution automation is perhaps the biggest barrier
|
||||
to Lean being used for PL.
|
||||
|
||||
\bibliographystyle{abbrvnat}
|
||||
\bibliography{cbpv.bib}
|
||||
|
||||
\end{document}
|
136
cbpv.tex
136
cbpv.tex
|
@ -3,13 +3,14 @@
|
|||
\usepackage[supertabular]{ottalt}
|
||||
\let\newlist\relax
|
||||
\let\renewlist\relax
|
||||
\usepackage[margin=1in]{geometry}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{mlmodern}
|
||||
\usepackage[margin=1in]{geometry}
|
||||
\usepackage{enumitem,float,booktabs,xspace,doi}
|
||||
\usepackage{enumitem,float,booktabs,xspace,xcolor,doi}
|
||||
\usepackage{amsmath,amsthm,amssymb}
|
||||
\usepackage[capitalize,nameinlink,noabbrev]{cleveref}
|
||||
\usepackage{mathpartir,mathtools,stmaryrd,latexsym}
|
||||
\usepackage[capitalize,nameinlink,noabbrev]{cleveref}
|
||||
\usepackage[numbers]{natbib}
|
||||
|
||||
\setlist{noitemsep}
|
||||
\hypersetup{
|
||||
|
@ -43,8 +44,8 @@
|
|||
\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).
|
||||
It follows work by Forster, Sch\"afer, Spies, and Stark \citep{cbpv} on mechanizing the metatheory of CBPV in Rocq,
|
||||
but instead adapts the proof technique from POPLMark Reloaded \citep{poplmark}.
|
||||
|
||||
Both proofs, and mine, follow the same sequence of steps:
|
||||
we define a logical relation that semantically interpret types as sets of terms,
|
||||
|
@ -60,7 +61,8 @@ 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),
|
||||
I have implemented a mutual induction tactic for Lean%
|
||||
\footnote{\url{https://github.com/ionathanch/MutualInduction}},
|
||||
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.
|
||||
|
@ -301,7 +303,7 @@ 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{} \\
|
||||
\fbox{$ \ottnt{v} \in \mathopen{\llbracket} \ottnt{A} \mathclose{\rrbracket} $} \quad \fbox{$ \ottnt{m} \in \mathopen{\llbracket} \ottnt{B} \mathclose{\rrbracket} $} \hfill \textit{semantic inhabitance of types} \\
|
||||
\begin{mathpar}
|
||||
\drule[]{LRPP-Unit-var}
|
||||
\drule[]{LRPP-Unit-unit}
|
||||
|
@ -716,6 +718,8 @@ traditional strong normalization of well typed terms holds as a corollary.
|
|||
|
||||
\section{Discussion} \label{sec:discussion}
|
||||
|
||||
\subsection{Proof Structure of Strong Normalization}
|
||||
|
||||
Overall, the inductive characterization of strongly normal terms is convenient to work with.
|
||||
Its congruence and inversion properties are exactly what are needed
|
||||
to show \nameref{lem:closure} and \nameref{lem:adequacy} of the logical relation,
|
||||
|
@ -797,4 +801,122 @@ to the particularities of the chosen reduction strategy.
|
|||
|
||||
\subsection{Lean for PL Metatheory}
|
||||
|
||||
The proof development involved in this report consists of nine files,
|
||||
as mentioned throughout.
|
||||
\Cref{tab:loc} gives the number of non-blank, non-comment lines of code for each file,
|
||||
which roughly reflects the amount of proof effort I required.
|
||||
The \texttt{Syntax.lean} file involves a lot of renaming and substitution proofs,
|
||||
but I copied these from prior proof developments with minimal changes to adapt them to CBPV.
|
||||
The actual semantic proofs in \texttt{NormalInd.lean}, \texttt{OpenSemantics.lean}, and \texttt{Soundness.lean}
|
||||
took roughly equal amounts of time to complete.
|
||||
As said in \cref{sec:sn-acc}, the proofs in \texttt{NormalAcc.lean}
|
||||
along with its dependency on \texttt{Reduction.lean} took nearly as much time to complete
|
||||
as the rest of the semantic proofs,
|
||||
while \texttt{LeftmostOutermost.lean} mostly mirrors \texttt{Reduction.lean}.
|
||||
The entire project, excluding this report, took about a week to complete.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{lr}
|
||||
\toprule
|
||||
File & LOC \\
|
||||
\midrule
|
||||
\texttt{Syntax.lean} & 252 \\
|
||||
\texttt{Typing.lean} & 48 \\
|
||||
\texttt{NormalInd.lean} & 192 \\
|
||||
\texttt{OpenSemantics.lean} & 107 \\
|
||||
\texttt{Soundness.lean} & 114 \\
|
||||
\texttt{Normalization.lean} & 48 \\
|
||||
\texttt{Reduction.lean} & 187 \\
|
||||
\texttt{NormalAcc.lean} & 291 \\
|
||||
\texttt{LeftmostOutermost.lean} & 276 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{Lean development files and lines of code}
|
||||
\label{tab:loc}
|
||||
\end{table}
|
||||
|
||||
One of the main technical challenges in mechanizing CBPV in Lean is dealing with mutual induction.
|
||||
While Lean currently supports mutually defined inductive types,
|
||||
the options for eliminating them are somewhat buggy and restricted.
|
||||
At the lower level,
|
||||
Lean generates independent eliminators (which they call \emph{recursors})
|
||||
for each of the mutual inductives,
|
||||
each with motives for all mutual inductives,
|
||||
similar to what \texttt{Scheme Induction for ... with Induction for ...}
|
||||
generates in Rocq.
|
||||
|
||||
Lean's induction tactic produces applications of the appropriate recursor,
|
||||
but does not support mutual inductives.
|
||||
In cases where induction on only a single inductive from the mutual definitions is needed,
|
||||
the induction tactic can be supplied with a custom recursor,
|
||||
in this case the appropriate inductive's recursor with all other motives
|
||||
instantiated to trivial propositions.
|
||||
Unfortunately, this fails because the tactic cannot handle induction cases
|
||||
with different numbers of indices in the inductive type,
|
||||
even if those other cases are eventually trivial.
|
||||
|
||||
Lean supports structural recursion on mutual inductives,
|
||||
which is implemented via a recursor on an auxiliary inductive
|
||||
that enables strong induction.
|
||||
However, this feature is currently a little buggy,
|
||||
and fails on some more complex inductive types.%
|
||||
\footnote{\url{https://github.com/leanprover/lean4/issues/1672}}
|
||||
Futhermore, writing proofs as recursive functions is unconventional,
|
||||
and isn't amenable to even simple automation that can automatically apply induction hypotheses.
|
||||
|
||||
Of course, it's possible to manually apply the recursors that Lean generates for each mutual inductive.
|
||||
This is inconvenient for several reasons:
|
||||
motives need to be explicitly specified, even when they're inferrable from the goals;
|
||||
cases with trivial motives still need to be explicitly proven;
|
||||
and induction cases are duplicated across the recursors.
|
||||
A partial solution, especially for the last inconvenience,
|
||||
is to generate the same kind of combined recursor that \texttt{Combined Scheme ...}
|
||||
does for Rocq, but it still requires explicit application.
|
||||
The mutual induction tactic I had implemented (outside of this project)
|
||||
aims to solve these issues.
|
||||
|
||||
In short, my mutual induction tactic targets multiple goals at a time.
|
||||
Applying the tactic on targets in mutually defined inductives from different goals
|
||||
applies their respective recursors, inferring motives from those goals,
|
||||
but deduplicates the induction cases, and introduces these cases as new subgoals.
|
||||
If a target and goal for a particular inductive is missing,
|
||||
the motive for that inductive is set as a trivially inhabited type,
|
||||
and all cases for that motive are automatically solved.
|
||||
|
||||
The mutual induction tactic has worked very well for this project.
|
||||
The mutual inductives involved are the value and computation terms and types (2 and 2),
|
||||
their typing judgements (2), the logical relation (2),
|
||||
the small-step reduction relation (2),
|
||||
and the mutually inductive definition of strongly neutral and normal terms and head reduction (4).
|
||||
The tactic was used for every proof by mutual induction mentioned here.
|
||||
Additionally, it was used twice for single induction
|
||||
(\ie all other motives are trivial): \rref{SN-Force-inv} and \nameref{cor:ext}.
|
||||
|
||||
Because the mutual induction tactic is merely a tactic and not a top-level construct,
|
||||
some amount of manipulation is still required to massage the proof state
|
||||
into one where the tactic can be used.
|
||||
Specifically, mutual theorems are first stated as some conjunction
|
||||
$(\forall v, P \gap v) \wedge (\forall m, Q \gap m)$,
|
||||
then split into two separate goals with targets $v, m$ introduced into the context,
|
||||
before mutual induction is applied to $v$ and $m$ with inferred motives $P$ and $Q$.
|
||||
This means that using the theorems individually requires projecting from the conjunction.
|
||||
There are discussions underway for introducing top-level syntax for mutual theorems,
|
||||
similar to Rocq's \texttt{Theorem ... with ...} vernacular,
|
||||
so that multiple goals are introduced automatically with their hypotheses.%
|
||||
\footnote{\url{https://leanprover.zulipchat.com/\#narrow/channel/239415-metaprogramming-.2F-tactics/topic/mutual.20induction.20tactic/near/504421657}}
|
||||
|
||||
Aside from mutual induction,
|
||||
the other technical challenge is proving all the renaming and substitution lemmas.
|
||||
There is no library like Autosubst 2 \citep{autosubst2} to automate defining and proving these lemmas.
|
||||
In multiple places, substitutions need to be massaged into different propositionally equal forms,
|
||||
and this massaging requires knowing exactly what equality is needed.
|
||||
For PL metatheory that doesn't involve mutual definitions
|
||||
but does involve some notion of binding and abstraction,
|
||||
the lack of a library for substitution automation is perhaps the biggest barrier
|
||||
to Lean being used for PL.
|
||||
|
||||
\bibliographystyle{abbrvnat}
|
||||
\bibliography{cbpv.bib}
|
||||
|
||||
\end{document}
|
Loading…
Reference in New Issue