Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mpri-2.4-public
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
POTTIER Francois
mpri-2.4-public
Commits
c24814e9
Commit
c24814e9
authored
Oct 27, 2017
by
REMY Didier
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
12d27e9b
054e4511
Changes
54
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
54 changed files
with
9603 additions
and
29 deletions
+9603
-29
README.md
README.md
+96
-29
coq/.gitignore
coq/.gitignore
+7
-0
coq/AutosubstExtra.v
coq/AutosubstExtra.v
+172
-0
coq/Autosubst_EOS.v
coq/Autosubst_EOS.v
+329
-0
coq/Autosubst_Env.v
coq/Autosubst_Env.v
+130
-0
coq/Autosubst_FreeVars.v
coq/Autosubst_FreeVars.v
+345
-0
coq/Autosubst_IsRen.v
coq/Autosubst_IsRen.v
+87
-0
coq/CPSContextSubstitution.v
coq/CPSContextSubstitution.v
+77
-0
coq/CPSCorrectness.v
coq/CPSCorrectness.v
+138
-0
coq/CPSCounterExample.v
coq/CPSCounterExample.v
+107
-0
coq/CPSDefinition.v
coq/CPSDefinition.v
+446
-0
coq/CPSIndifference.v
coq/CPSIndifference.v
+262
-0
coq/CPSKubstitution.v
coq/CPSKubstitution.v
+120
-0
coq/CPSRenaming.v
coq/CPSRenaming.v
+92
-0
coq/CPSSimulation.v
coq/CPSSimulation.v
+177
-0
coq/CPSSimulationWithoutLet.v
coq/CPSSimulationWithoutLet.v
+137
-0
coq/CPSSpecialCases.v
coq/CPSSpecialCases.v
+48
-0
coq/CPSSubstitution.v
coq/CPSSubstitution.v
+149
-0
coq/ClosureConversion.v
coq/ClosureConversion.v
+349
-0
coq/DemoEqReasoning.v
coq/DemoEqReasoning.v
+73
-0
coq/DemoSyntaxReduction.v
coq/DemoSyntaxReduction.v
+250
-0
coq/Even.v
coq/Even.v
+98
-0
coq/FixExtra.v
coq/FixExtra.v
+20
-0
coq/LambdaCalculusBigStep.v
coq/LambdaCalculusBigStep.v
+532
-0
coq/LambdaCalculusFreeVars.v
coq/LambdaCalculusFreeVars.v
+126
-0
coq/LambdaCalculusInterpreter.v
coq/LambdaCalculusInterpreter.v
+218
-0
coq/LambdaCalculusParallelReduction.v
coq/LambdaCalculusParallelReduction.v
+174
-0
coq/LambdaCalculusReduction.v
coq/LambdaCalculusReduction.v
+619
-0
coq/LambdaCalculusStandardization.v
coq/LambdaCalculusStandardization.v
+679
-0
coq/LambdaCalculusSyntax.v
coq/LambdaCalculusSyntax.v
+197
-0
coq/LambdaCalculusValues.v
coq/LambdaCalculusValues.v
+179
-0
coq/Makefile
coq/Makefile
+2
-0
coq/Makefile.coq
coq/Makefile.coq
+188
-0
coq/MetalBigStep.v
coq/MetalBigStep.v
+313
-0
coq/MetalSyntax.v
coq/MetalSyntax.v
+432
-0
coq/MyList.v
coq/MyList.v
+125
-0
coq/MyTactics.v
coq/MyTactics.v
+182
-0
coq/Option.v
coq/Option.v
+120
-0
coq/README.md
coq/README.md
+17
-0
coq/Relations.v
coq/Relations.v
+498
-0
coq/Sequences.v
coq/Sequences.v
+321
-0
ocaml/EvalCBNCPS.ml
ocaml/EvalCBNCPS.ml
+164
-0
ocaml/EvalCBVCPS.ml
ocaml/EvalCBVCPS.ml
+208
-0
ocaml/EvalCBVExercise.ml
ocaml/EvalCBVExercise.ml
+71
-0
ocaml/Graph.ml
ocaml/Graph.ml
+203
-0
ocaml/Lambda.ml
ocaml/Lambda.ml
+175
-0
ocaml/NewtonRaphson.ml
ocaml/NewtonRaphson.ml
+151
-0
slides/fpottier-00.pdf
slides/fpottier-00.pdf
+0
-0
slides/fpottier-01a.pdf
slides/fpottier-01a.pdf
+0
-0
slides/fpottier-01b.pdf
slides/fpottier-01b.pdf
+0
-0
slides/fpottier-02.pdf
slides/fpottier-02.pdf
+0
-0
slides/fpottier-03.pdf
slides/fpottier-03.pdf
+0
-0
slides/fpottier-04.pdf
slides/fpottier-04.pdf
+0
-0
slides/fpottier-05.pdf
slides/fpottier-05.pdf
+0
-0
No files found.
README.md
View file @
c24814e9
# Functional programming and type systems (2017-2018)
[
The official MPRI
page
](
https://wikimpri.dptinfo.ens-cachan.fr/doku.php?id=cours:c-2-4-2
)
This page supplements
[
the official page of MPRI 2-4
](
https://wikimpri.dptinfo.ens-cachan.fr/doku.php?id=cours:c-2-4-2
)
.
## Location
## Location
and duration
The lessons take place at University of Paris 7 - Denis Diderot,
Batiment Sophie Germain in room 2035 on Fridays at 12:45 and ends at 15:30.
There will be a break of 15' in the middle of the course.
The lectures take place at University Paris 7 - Denis Diderot,
Bâtiment Sophie Germain, in room 2035.
They are scheduled on Fridays from 12:45 to 15:30.
There is a 15-minute break in the middle of each lecture.
## Teachers
...
...
@@ -20,6 +22,7 @@ There will be a break of 15' in the middle of the course.
This course presents the principles and formalisms that underlie many of
today's typed functional programming languages.
(Here are some
[
introductory slides
](
slides/fpottier-00.pdf
)
.)
The course is made up of four parts and can be split after the first two
parts.
...
...
@@ -43,8 +46,8 @@ systems. We study parametric polymorphism (as in System F and ML), data
types and type abstraction. We show syntactic type soundness (via progress
and subject reduction) by reasoning by induction on typing derivations. We
also show how to obtain semantic properties via logical relations by
reasoning by induction on the structure of types.
We also
introduce
subtyping
and row polymorphism and illustrate typing
problems induced by
reasoning by induction on the structure of types.
Finally, we
introduce
subtyping
, row polymorphism, and illustrate the
problems induced by
side effects (references) and the need for the value restriction.
The third part of the course describes more advanced features of type
...
...
@@ -61,25 +64,50 @@ We also show the limits of dependently-typed functional programming.
### Functional Programming: Under the Hood
*
(22/09/2017) From a small-step operational semantics...
*
(29/09/2017) ... to an efficient interpreter. (2 weeks.)
*
(06/10/2017) Compiling away first-class functions: closure conversion, defunctionalization.
*
(13/10/2017) Compiling away the call stack: the CPS transformation.
*
(20/10/2017) Equational reasoning and program optimizations.
*
(22/09/2017)
Introduction (
[
slides 00
](
slides/fpottier-00.pdf
)
).
Syntax and operational semantics, on paper and on a machine
(
[
slides 01a
](
slides/fpottier-01a.pdf
)
)
(
[
slides 01b
](
slides/fpottier-01b.pdf
)
).
*
Newton-Raphson in OCaml (
[
solution
](
ocaml/NewtonRaphson.ml
)
).
*
1 is not even in Coq (
[
Even.v
](
coq/Even.v
)
).
*
(29/09/2017)
From a small-step semantics down to an efficient verified interpreter,
in several stages
(
[
Coq demo
](
coq/DemoSyntaxReduction.v
)
)
(
[
slides 02
](
slides/fpottier-02.pdf
)
)
(
[
OCaml code
](
ocaml/Lambda.ml
)
)
(
[
Coq repo
](
coq/
)
).
*
(06/10/2017) Compiling away first-class functions:
closure conversion, defunctionalization
(
[
slides 03
](
slides/fpottier-03.pdf
)
)
(
[
Coq repo
](
coq/
)
).
*
(13/10/2017) Making the stack explicit: the CPS transformation
(
[
slides 04
](
slides/fpottier-04.pdf
)
)
(
[
Coq repo
](
coq/
)
).
*
Transforming a call-by-value interpreter
(
[
exercise
](
ocaml/EvalCBVExercise.ml
)
,
[
solution
](
ocaml/EvalCBVCPS.ml
)
).
*
Transforming a call-by-name interpreter
(
[
solution
](
ocaml/EvalCBNCPS.ml
)
).
*
Transforming a graph traversal
(
[
solution
](
ocaml/Graph.ml
)
).
*
(20/10/2017) Equational reasoning and program optimizations
(
[
slides 05
](
slides/fpottier-05.pdf
)
)
(
[
Coq mini-demo
](
coq/DemoEqReasoning.v
)
).
### Metatheory of Typed Programming Languages
*
(15/09/2017)
[
Metatheory of System F
](
http://gallium.inria.fr/~remy/mpri/slides1.pdf
)
(See also
[
intro
](
http://gallium.inria.fr/~remy/mpri/slides8.pdf
)
,
and chap
[
1
](
http://gallium.inria.fr/~remy/mpri/cours1.pdf
)
and
[
2
](
http://gallium.inria.fr/~remy/mpri/cours2.pdf
)
(See also
[
intro
](
http://gallium.inria.fr/~remy/mpri/slides8.pdf
)
,
and chap
[
1
](
http://gallium.inria.fr/~remy/mpri/cours1.pdf
)
and
[
2
](
http://gallium.inria.fr/~remy/mpri/cours2.pdf
)
of
[
course notes
](
http://gallium.inria.fr/~remy/mpri/cours.pdf
)
)
*
(27/10/2017)
[ADTs, existential types, GADTs]
(http://gallium.inria.fr/~remy/mpri/slides2.pdf).
*
(03/11/2017) Logical relations.
*
(10/11/2017) Subtyping. Rows.
*
(10/11/2017) Subtyping. Rows.
*
(17/11/2017) References, Value restriction, Side effects.
### Advanced Aspects of Type Systems
...
...
@@ -108,24 +136,24 @@ who split the course.
Although the course has changed, you may still have a look at previous exams
available with solutions:
-
mid-term exam 2016-2017:
-
mid-term exam 2016-2017:
[
Record concatenation
](
http://gallium.inria.fr/~remy/mpri/exams/partiel-2016-2017.pdf
)
-
mid-term exam 2015-2016:
-
mid-term exam 2015-2016:
[
Type containment
](
http://gallium.inria.fr/~remy/mpri/exams/partiel-2015-2016.pdf
)
-
final exam 2014-2015:
[
Copatterns
](
http://gallium.inria.fr/~remy/mpri/exams/final-2014-2015.pdf
)
-
mid-term exam 2014-2015:
-
mid-term exam 2014-2015:
[
Information flow
](
http://gallium.inria.fr/~remy/mpri/exams/partiel-2014-2015.pdf
)
-
final exam 2013-2014:
-
final exam 2013-2014:
[
Operation on records
](
http://gallium.inria.fr/~remy/mpri/exams/final-2013-2014.pdf
)
-
mid-term exam 2013-2014:
-
mid-term exam 2013-2014:
[
Typechecking Effects
](
http://gallium.inria.fr/~remy/mpri/exams/partiel-2013-2014.pdf
)
-
final exam 2012-2013:
-
final exam 2012-2013:
[
Refinement types
](
http://gallium.inria.fr/~remy/mpri/exams/final-2012-2013.pdf
)
-
mid-term exam 2012-2013:
-
mid-term exam 2012-2013:
[
Variations on ML
](
http://gallium.inria.fr/~remy/mpri/exams/partiel-2012-2013.pdf
)
-
final exam 2011-2012:
-
final exam 2011-2012:
[
Intersection types
](
http://gallium.inria.fr/~remy/mpri/exams/final-2011-2012.pdf
)
-
mid-term exam 2011-2012:
-
mid-term exam 2011-2012:
[
Parametricity
](
http://gallium.inria.fr/~remy/mpri/exams/partiel-2011-2012.pdf
)
-
final exam 2010-2011:
[
Compiling a language with subtyping
](
http://gallium.inria.fr/~xleroy/mpri/2-4/exam-2010-2011.pdf
)
...
...
@@ -135,19 +163,58 @@ available with solutions:
## Recommended software
OCaml 4.0x and Coq
**8.5**
.
Please install
[
opam
](
https://opam.ocaml.org/doc/Install.html
)
first
.
Once you have installed
[
opam
](
https://opam.ocaml.org/doc/Install.html
)
, use
the following commands:
Then, install OCaml 4.0x and Coq
**8.5**
via
the following commands:
```
bash
opam init
--comp
=
4.05
# for instance
opam repo add coq-released https://coq.inria.fr/opam/released
opam update
opam
install
-j4
-v
coq.8.5.3
```
(Do
*not*
install Coq 8.6. The version of AutoSubst that I am using is
not compatible with it. If for some reason you need Coq 8.6, or have
already installed Coq 8.6, note that
`opam switch`
can be used to let
multiple versions of Coq coexist.)
Please also install François Pottier's
[
variant
](
https://github.com/fpottier/autosubst
)
of the
[
AutoSubst
](
https://www.ps.uni-saarland.de/autosubst/
)
library:
```
bash
git clone git@github.com:fpottier/autosubst.git
make
-C
autosubst
install
```
In order to use Coq inside
`emacs`
,
[
ProofGeneral
](
https://proofgeneral.github.io/
)
is highly recommended.
Here is a suggested installation script:
```
bash
rm
-rf
/tmp/PG
cd
/tmp
git clone git@github.com:ProofGeneral/PG.git
cd
PG
EMACS
=
/Applications/Aquamacs.app/Contents/MacOS/Aquamacs
if
[
!
-x
$EMACS
]
;
then
EMACS
=
emacs
fi
make
EMACS
=
$EMACS
compile
TARGET
=
/usr/local/share/emacs/site-lisp/ProofGeneral
sudo rm
-rf
$TARGET
sudo mv
/tmp/PG
$TARGET
```
Enable ProofGeneral by adding the following line to your
`.emacs`
file:
```
elisp
(
load-file
"/usr/local/share/emacs/site-lisp/ProofGeneral/generic/proof-site.el"
)
```
If desired, ProofGeneral can be further
[
customized
](
https://proofgeneral.github.io/doc/userman/ProofGeneral_9/
)
.
## Bibliography
[
Types and Programming Languages
](
https://mitpress.mit.edu/books/types-and-programming-languages
)
,
[
Types and Programming Languages
](
https://mitpress.mit.edu/books/types-and-programming-languages
)
,
Benjamin C. Pierce, MIT Press, 2002.
[
Advanced Topics in Types and Programming Languages
](
https://www.cis.upenn.edu/~bcpierce/attapl/
)
,
...
...
coq/.gitignore
0 → 100644
View file @
c24814e9
*.vo
*.glob
*.v.d
.*.aux
.coq-native
_CoqProject
*~
coq/AutosubstExtra.v
0 → 100644
View file @
c24814e9
Require
Import
Omega
.
Require
Import
Autosubst
.
Autosubst
.
Require
Import
MyTactics
.
(
*
TEMPORARY
*
)
(
*
--------------------------------------------------------------------------
*
)
(
*
A
more
recognizable
notation
for
lifting
.
*
)
Notation
lift
i
t
:=
(
t
.[
ren
(
+
i
)]).
(
*
--------------------------------------------------------------------------
*
)
Section
Extras
.
Context
A
`
{
Ids
A
,
Rename
A
,
Subst
A
,
SubstLemmas
A
}
.
Lemma
up_ren
:
forall
xi
,
ren
(
upren
xi
)
=
up
(
ren
xi
).
Proof
.
intros
.
autosubst
.
Qed
.
Lemma
upn_ren
:
forall
i
xi
,
ren
(
iterate
upren
i
xi
)
=
upn
i
(
ren
xi
).
Proof
.
induction
i
;
intros
.
{
reflexivity
.
}
{
rewrite
<-
fold_up_upn
.
rewrite
<-
IHi
.
asimpl
.
reflexivity
.
}
Qed
.
Lemma
plus_upn
:
(
*
close
to
[
up_liftn
]
*
)
forall
i
sigma
,
(
+
i
)
>>>
upn
i
sigma
=
sigma
>>
ren
(
+
i
).
Proof
.
induction
i
;
intros
.
{
rewrite
iterate_0
.
autosubst
.
}
{
rewrite
iterate_S
.
asimpl
.
rewrite
IHi
.
autosubst
.
}
Qed
.
Lemma
up_sigma_up_ren
:
forall
t
i
sigma
,
t
.[
up
sigma
].[
up
(
ren
(
+
i
))]
=
t
.[
up
(
ren
(
+
i
))].[
upn
(
1
+
i
)
sigma
].
Proof
.
intros
.
asimpl
.
rewrite
plus_upn
.
asimpl
.
reflexivity
.
Qed
.
Lemma
upn_k_sigma_x
:
forall
k
sigma
x
,
x
<
k
->
upn
k
sigma
x
=
ids
x
.
Proof
.
induction
k
;
intros
;
asimpl
.
{
omega
.
}
{
destruct
x
;
asimpl
.
{
eauto
.
}
{
rewrite
IHk
by
omega
.
autosubst
.
}
}
Qed
.
Lemma
push_substitution_last
:
forall
t
v
i
,
t
.[
v
.
:
ren
(
+
i
)]
=
t
.[
up
(
ren
(
+
i
))].[
v
/
].
Proof
.
intros
.
autosubst
.
Qed
.
Lemma
push_substitution_last_up_hoist
:
forall
t
v
i
j
,
t
.[
up
(
v
.
:
ren
(
+
i
))].[
up
(
ren
(
+
j
))]
=
t
.[
up
(
up
(
ren
(
+
j
+
i
)))].[
up
(
lift
j
v
.
:
ids
)].
Proof
.
intros
.
autosubst
.
Qed
.
Lemma
lift_lift
:
forall
i
j
t
,
lift
i
(
lift
j
t
)
=
lift
(
i
+
j
)
t
.
Proof
.
intros
.
autosubst
.
Qed
.
Lemma
lift_upn
:
forall
t
i
sigma
,
(
lift
i
t
).[
upn
i
sigma
]
=
lift
i
t
.[
sigma
].
Proof
.
intros
.
asimpl
.
erewrite
plus_upn
.
reflexivity
.
Qed
.
Lemma
lift_up
:
forall
t
sigma
,
(
lift
1
t
).[
up
sigma
]
=
lift
1
t
.[
sigma
].
Proof
.
intros
.
change
up
with
(
upn
1
).
eapply
lift_upn
.
Qed
.
Lemma
up_sigma_f
:
forall
(
sigma
:
var
->
A
)
(
f
:
A
->
A
),
f
(
ids
0
)
=
ids
0
->
(
forall
i
t
,
lift
i
(
f
t
)
=
f
(
lift
i
t
))
->
up
(
sigma
>>>
f
)
=
up
sigma
>>>
f
.
Proof
.
intros
.
f_ext
.
intros
[
|
x
];
asimpl
;
eauto
.
Qed
.
Lemma
upn_sigma_f
:
forall
(
sigma
:
var
->
A
)
(
f
:
A
->
A
),
f
(
ids
0
)
=
ids
0
->
(
forall
i
t
,
lift
i
(
f
t
)
=
f
(
lift
i
t
))
->
forall
i
,
upn
i
(
sigma
>>>
f
)
=
upn
i
sigma
>>>
f
.
Proof
.
induction
i
;
intros
.
{
reflexivity
.
}
{
do
2
rewrite
<-
fold_up_upn
.
rewrite
IHi
.
erewrite
up_sigma_f
by
eauto
.
reflexivity
.
}
Qed
.
Lemma
upn_theta_sigma_ids
:
forall
theta
sigma
i
,
theta
>>
sigma
=
ids
->
upn
i
theta
>>
upn
i
sigma
=
ids
.
Proof
.
intros
theta
sigma
i
Hid
.
rewrite
up_comp_n
.
rewrite
Hid
.
rewrite
up_id_n
.
reflexivity
.
Qed
.
Lemma
up_theta_sigma_ids
:
forall
theta
sigma
,
theta
>>
sigma
=
ids
->
up
theta
>>
up
sigma
=
ids
.
Proof
.
change
up
with
(
upn
1
).
eauto
using
upn_theta_sigma_ids
.
Qed
.
Lemma
scons_scomp
:
forall
(
T
:
A
)
Gamma
theta
,
T
.[
theta
]
.
:
(
Gamma
>>
theta
)
=
(
T
.
:
Gamma
)
>>
theta
.
Proof
.
intros
.
autosubst
.
Qed
.
(
*
BUG
:
the
two
sides
of
this
equation
are
distinct
,
yet
they
are
printed
identically
.
*
)
Goal
forall
v
f
,
v
.
:
(
ids
>>>
f
)
=
(
v
.
:
ids
)
>>>
f
.
Proof
.
intros
.
Fail
reflexivity
.
Abort
.
End
Extras
.
(
*
This
incantation
means
that
[
eauto
with
autosubst
]
can
use
the
tactic
[
autosubst
]
to
prove
an
equality
.
*
)
Hint
Extern
1
(
_
=
_
)
=>
autosubst
:
autosubst
.
(
*
This
incantation
means
that
[
eauto
with
autosubst
]
can
use
the
lemmas
whose
names
are
listed
here
.
This
is
useful
when
an
equality
involves
metavariables
,
so
the
tactic
[
autosubst
]
fails
.
*
)
Hint
Resolve
scons_scomp
:
autosubst
.
(
*
--------------------------------------------------------------------------
*
)
coq/Autosubst_EOS.v
0 → 100644
View file @
c24814e9
Require
Import
Omega
.
Require
Import
Autosubst
.
Autosubst
.
Require
Import
AutosubstExtra
.
(
*
just
for
[
upn_ren
]
*
)
Require
Import
MyTactics
.
(
*
TEMPORARY
*
)
(
*
This
file
defines
the
construction
[
eos
x
t
],
which
can
be
understood
as
an
end
-
of
-
scope
mark
for
[
x
]
in
the
term
[
t
].
*
)
(
*
It
also
defines
the
single
-
variable
substitution
t
.[
u
// x], which is the
substitution
of
[
u
]
for
[
x
]
in
[
t
].
*
)
(
*
--------------------------------------------------------------------------
*
)
Section
EOS
.
Context
{
A
}
`
{
Ids
A
,
Rename
A
,
Subst
A
,
SubstLemmas
A
}
.
(
*
The
substitution
[
Var
0
.
:
Var
1
.
:
...
.
:
Var
(
x
-
1
)
.
:
Var
(
x
+
1
)
.
:
...]
does
not
have
[
Var
x
]
in
its
codomain
.
Thus
,
applying
this
substitution
to
a
term
[
t
]
can
be
understood
as
an
end
-
of
-
scope
construct
:
it
means
`
`end
the
scope
of
[
x
]
in
[
t
]
''
.
We
write
[
eos
x
t
]
for
this
construct
.
It
is
also
known
as
[
adbmal
]
:
see
Hendriks
and
van
Oostrom
,
https:
//doi.org/10.1007/978-3-540-45085-6_11 *)
(
*
There
are
at
least
two
ways
of
defining
the
above
substitution
.
One
way
is
to
define
it
in
terms
of
AutoSubst
combinators
:
*
)
Definition
eos_var
x
:
var
->
var
:=
(
iterate
upren
x
(
+
1
)).
Definition
eos
x
t
:=
t
.[
ren
(
eos_var
x
)].
Lemma
eos_eq
:
forall
x
t
,
t
.[
upn
x
(
ren
(
+
1
))]
=
eos
x
t
.
Proof
.
intros
.
unfold
eos
,
eos_var
.
erewrite
upn_ren
by
tc
.
reflexivity
.
Qed
.
(
*
Another
way
is
to
define
directly
as
a
function
of
type
[
var
->
var
].
*
)
Definition
lift_var
x
:
var
->
var
:=
fun
y
=>
if
le_gt_dec
x
y
then
1
+
y
else
y
.
(
*
The
two
definitions
coincide
:
*
)
Lemma
upren_lift_var
:
forall
x
,
upren
(
lift_var
x
)
=
lift_var
(
S
x
).
Proof
.
intros
.
f_ext
;
intros
[
|
y
].
{
reflexivity
.
}
{
simpl
.
unfold
lift_var
,
var
.
dblib_by_cases
;
omega
.
}
Qed
.
Lemma
eos_var_eq_lift_var
:
eos_var
=
lift_var
.
Proof
.
(
*
An
uninteresting
proof
.
*
)
f_ext
;
intros
x
.
unfold
eos_var
.
induction
x
.
{
reflexivity
.
}
{
rewrite
iterate_S
.
rewrite
IHx
.
rewrite
upren_lift_var
.
reflexivity
.
}
Qed
.
(
*
--------------------------------------------------------------------------
*
)
(
*
[
eos
]
enjoys
certain
commutation
laws
.
*
)
(
*
Ending
the
scope
of
variable
[
k
],
then
the
scope
of
variable
[
s
],
is
the
same
as
first
ending
the
scope
of
variable
[
1
+
s
],
then
ending
the
scope
of
variable
[
k
].
This
holds
provided
[
k
<=
s
]
is
true
,
i
.
e
.,
[
k
]
is
the
most
recently
-
introduced
variable
.
*
)
Lemma
lift_var_lift_var
:
forall
k
s
,
k
<=
s
->
lift_var
s
>>>
lift_var
k
=
lift_var
k
>>>
lift_var
(
S
s
).
Proof
.
(
*
By
case
analysis
.
*
)
intros
.
f_ext
;
intros
x
.
asimpl
.
unfold
lift_var
,
var
.
dblib_by_cases
;
omega
.
Qed
.
Lemma
eos_eos
:
forall
k
s
t
,
k
<=
s
->
eos
k
(
eos
s
t
)
=
eos
(
1
+
s
)
(
eos
k
t
).
Proof
.
intros
.
unfold
eos
.
asimpl
.
rewrite
eos_var_eq_lift_var
.
rewrite
lift_var_lift_var
by
eauto
.
reflexivity
.
Qed
.
(
*
What
about
the
case
where
[
k
]
is
the
least
recently
-
introduced
variable
?
It
is
obtained
by
symmetry
,
of
course
.
*
)
Lemma
eos_eos_reversed
:
forall
k
s
t
,
k
>=
s
+
1
->
eos
k
(
eos
s
t
)
=
eos
s
(
eos
(
k
-
1
)
t
).
Proof
.
intros
.
replace
k
with
(
1
+
(
k
-
1
))
by
omega
.
rewrite
<-
eos_eos
by
omega
.
replace
(
1
+
(
k
-
1
)
-
1
)
with
(
k
-
1
)
by
omega
.
reflexivity
.
Qed
.
(
*
--------------------------------------------------------------------------
*
)
(
*
Single
-
variable
substitutions
.
*
)
(
*
[
subst_var
u
x
]
is
the
substitution
of
[
u
]
for
[
x
].
*
)
(
*
We
give
a
direct
definition
of
it
as
a
function
of
type
[
var
->
term
],
defined
by
cases
.
I
don
'
t
know
if
it
could
also
be
nicely
defined
in
terms
of
the
basic
combinators
of
de
Bruijn
algebra
.
Note
that
the
candidate
definition
[
upn
x
(
t
.
:
ids
)]
is
WRONG
when
[
x
>
0
].
*
)
Definition
subst_var
(
u
:
A
)
(
x
y
:
var
)
:
A
:=
match
lt_eq_lt_dec
y
x
with
|
inleft
(
left
_
)
=>
ids
y
|
inleft
(
right
_
)
=>
u
|
inright
_
=>
ids
(
y
-
1
)
end
.
(
*
A
nice
notation
:
[
t
.[
u
// x]] is the substitution of [u] for [x] in [t]. *)
Notation
"t .[ u // x ]"
:=
(
subst
(
subst_var
u
x
)
t
)
(
at
level
2
,
u
at
level
200
,
left
associativity
,
format
"t .[ u // x ]"
)
:
subst_scope
.
(
*
The
following
laws
serve
as
sanity
checks
:
we
got
the
definition
right
.
*
)
Lemma
subst_var_miss_1
:
forall
x
y
u
,
y
<
x
->
(
ids
y
).[
u
// x] = ids y.
Proof
.
intros
.
asimpl
.
unfold
subst_var
.
dblib_by_cases
.
reflexivity
.
Qed
.
Lemma
subst_var_match
:
forall
x
u
,
(
ids
x
).[
u
// x ] = u.
Proof
.
intros
.
asimpl
.
unfold
subst_var
.
dblib_by_cases
.
reflexivity
.
Qed
.
Lemma
subst_var_miss_2
:
forall
x
y
u
,
x
<
y
->
(
ids
y
).[
u
// x] = ids (y - 1).
Proof
.
intros
.
asimpl
.
unfold
subst_var
.
dblib_by_cases
.
reflexivity
.
Qed
.
(
*
In
the
special
case
where
[
x
]
is
0
,
the
substitution
[
t
// 0] can also
be
written
[
t
/
],
which
is
an
AutoSubst
notation
for
[
t
.
:
ids
].
*
)
Lemma
subst_var_0
:
forall
t
u
,
t
.[
u
// 0] = t.[u/].
Proof
.
intros
.
f_equal
.
clear
t
.
f_ext
.
intros
[
|
x
].
{
reflexivity
.
}
{
unfold
subst_var
.
simpl
.
f_equal
.
omega
.
}
Qed
.
(
*
--------------------------------------------------------------------------
*
)
(
*
A
cancellation
law
:
substituting
for
a
variable
[
x
]
that
does
not
occur
in
[
t
]
yields
just
[
t
].
In
other
words
,
a
substitution
for
[
x
]
vanishes
when
it
reaches
[
eos
x
_
].
*
)
(
*
In
informal
syntax
,
this
lemma
would
be
written
:
t
[
u
/
x
]
=
t
under
the
hypothesis
that
x
does
not
occur
free
in
t
.
In
de
Bruijn
style
,
the
statement
is
just
as
short
,
and
does
not
have
a
side
condition
.
Instead
,
it
requires
an
explicit
[
eos
x
_
]
to
appear
at
the
root
of
the
term
to
which
the
substitution
is
applied
;
this
may
require
rewriting
before
this
lemma
can
be
applied
.
*
)
Lemma
subst_eos
:
forall
x
t
u
,
(
eos
x
t
).[
u
// x] = t.
Proof
.
intros
.
(
*
Again
,
let
'
s
simplify
this
first
.
*
)
unfold
eos
.
asimpl
.
(
*
Aha
!
We
can
forget
about
[
t
],
and
focus
on
proving
that
two
substitutions
are
equal
.
To
do
so
,
it
is
sufficient
that
their
actions
on
a
variable
[
y
]
are
the
same
.
*
)
rewrite
<-
subst_id
.
f_equal
.
clear
t
.
f_ext
.
intro
y
.
(
*
The
proof
is
easy
if
we
replace
[
eos_var
]
with
[
lift_var
].
*
)
rewrite
eos_var_eq_lift_var
.
simpl
.
unfold
subst_var
,
lift_var
.
dblib_by_cases
;
f_equal
;
omega
.
Qed
.
(
*
The
above
property
allows
us
to
prove
that
[
eos
x
_
]
is
injective
.
Indeed
,
it
has
an
inverse
,
namely
[
u
// x], where [u] is arbitrary. *)
Lemma
eos_injective
:
forall
x
t1
t2
,
eos
x
t1
=
eos
x
t2
->
t1
=
t2
.
Proof
.
intros
.
pose
(
u
:=
t1
).
(
*
dummy
*
)
erewrite
<-
(
subst_eos
x
t1
u
).
erewrite
<-
(
subst_eos
x
t2
u
).