mpri-funcprog-project/coq/LambdaCalculusSyntax.v
2017-10-05 17:57:33 +02:00

198 lines
4.9 KiB
Coq

Require Import Coq.Wellfounded.Inverse_Image.
Require Import MyTactics.
Require Export Autosubst.Autosubst.
Require Export AutosubstExtra.
Require Export Autosubst_IsRen.
(* Require Export Autosubst_EOS. *)
Require Export Autosubst_FreeVars.
(* The syntax of the lambda-calculus. *)
Inductive term :=
| Var (x : var)
| Lam (t : {bind term})
| App (t1 t2 : term)
| Let (t1 : term) (t2 : {bind term})
.
Instance Ids_term : Ids term. derive. Defined.
Instance Rename_term : Rename term. derive. Defined.
Instance Subst_term : Subst term. derive. Defined.
Instance SubstLemmas_term : SubstLemmas term. derive. Qed.
Instance IdsLemmas_term : IdsLemmas term.
Proof. econstructor. intros. injections. eauto. Qed.
(* If the image of [t] through a substitution is a variable, then [t] must
itself be a variable. *)
Lemma subst_is_var:
forall t sigma x,
t.[sigma] = ids x ->
exists y,
t = ids y.
Proof.
intros ? ? ? Heq. destruct t; compute in Heq; solve [ eauto | congruence ].
Qed.
(* The identity substitution [ids] is injective. *)
Lemma inj_ids:
forall x y,
ids x = ids y ->
x = y.
Proof.
intros ? ? Heq. compute in Heq. congruence.
Qed.
(* If the composition of two substitutions [sigma1] and [sigma2] is the
identity substitution, then [sigma1] must be a renaming. *)
Lemma ids_implies_is_ren:
forall sigma1 sigma2,
sigma1 >> sigma2 = ids ->
is_ren sigma1.
Proof.
intros ? ? Hid.
eapply prove_is_ren; [ eapply inj_ids | intros x ].
eapply subst_is_var with (sigma := sigma2) (x := x).
rewrite <- Hid. reflexivity.
Qed.
Hint Resolve ids_implies_is_ren : is_ren obvious.
(* The size of a term. *)
Fixpoint size (t : term) : nat :=
match t with
| Var _ => 0
| Lam t => 1 + size t
| App t1 t2
| Let t1 t2 => 1 + size t1 + size t2
end.
(* The size of a term is preserved by renaming. *)
Lemma size_renaming:
forall t sigma,
is_ren sigma ->
size t.[sigma] = size t.
Proof.
induction t; intros sigma Hsigma; asimpl;
repeat (match goal with h: forall sigma, _ |- _ => rewrite h by obvious; clear h end);
try reflexivity.
(* [Var] *)
{ destruct Hsigma as [ xi ? ]. subst. reflexivity. }
Qed.
(* The [size] function imposes a well-founded ordering on terms. *)
Lemma smaller_wf:
well_founded (fun t1 t2 => size t1 < size t2).
Proof.
eauto using wf_inverse_image, lt_wf.
Qed.
(* The tactic [size_induction] facilitates proofs by induction on the
size of a term. The following lemmas are used in the construction
of this tactic. *)
Lemma size_induction_intro:
forall (P : term -> Prop),
(forall n t, size t < n -> P t) ->
(forall t, P t).
Proof.
eauto. (* just instantiate [n] with [size t + 1] *)
Defined.
Lemma size_induction_induction:
forall (P : term -> Prop),
(forall n, (forall t, size t < n -> P t) -> (forall t, size t < S n -> P t)) ->
(forall n t, size t < n -> P t).
Proof.
intros P IH. induction n; intros.
{ false. eapply Nat.nlt_0_r. eauto. }
{ eauto. }
Defined.
Lemma size_induction:
forall (P : term -> Prop),
(forall n, (forall t, size t < n -> P t) -> (forall t, size t < S n -> P t)) ->
(forall t, P t).
Proof.
intros P IH.
eapply size_induction_intro.
eapply size_induction_induction.
eauto.
Defined.
Ltac size_induction :=
(* We assume the goal is of the form [forall t, P t]. *)
intro t; pattern t;
match goal with |- ?P t =>
simpl; eapply (@size_induction P); clear
end;
intros n IH t Htn.
(* The goal should now be of the form [P t]
with a hypothesis [IH: (forall t, size t < n -> P t]
and a hypothesis [Htn: size t < S n]. *)
(* The tactic [size] proves goals of the form [size t < n]. The tactic
[obvious] is also extended to prove such goals. *)
Hint Extern 1 (size ?t.[?sigma] < ?n) =>
rewrite size_renaming by obvious
: size obvious.
Hint Extern 1 (size ?t < ?n) =>
simpl in *; omega
: size obvious.
Ltac size :=
eauto with size.
(* The following is a direct proof of [smaller_wf]. We do not use any
preexisting lemmas, and end the proof with [Defined] instead of [Qed],
so as to make the proof term transparent. Also, we avoid the tactic
[omega], which produces huge proof terms. This allows Coq to compute
with functions that are defined by well-founded recursion. *)
Lemma smaller_wf_transparent:
well_founded (fun t1 t2 => size t1 < size t2).
Proof.
unfold well_founded. size_induction.
constructor; intros u Hu.
eapply IH. eapply lt_S_n. eapply le_lt_trans; eauto.
Defined.
(* The following lemmas can be useful in situations where the tactic
[asimpl] performs too much simplification. *)
Lemma subst_var:
forall x sigma,
(Var x).[sigma] = sigma x.
Proof.
autosubst.
Qed.
Lemma subst_lam:
forall t sigma,
(Lam t).[sigma] = Lam (t.[up sigma]).
Proof.
autosubst.
Qed.
Lemma subst_app:
forall t1 t2 sigma,
(App t1 t2).[sigma] = App t1.[sigma] t2.[sigma].
Proof.
autosubst.
Qed.
Lemma subst_let:
forall t1 t2 sigma,
(Let t1 t2).[sigma] = Let t1.[sigma] t2.[up sigma].
Proof.
autosubst.
Qed.