From Undecidability Require L.L L.Util.L_facts.
Import L (term, var, app, lam).
Import L_facts (closed, bound, closed_dcl, dclvar, dclApp, dcllam).
From Undecidability Require Import wCBN.
Require Import PeanoNat Lia.
Require Import ssreflect ssrbool ssrfun.
Set Default Goal Selector "!".
Lemma ext_ren_term xi1 xi2 t : (forall n, xi1 n = xi2 n) -> ren xi1 t = ren xi2 t.
Proof.
elim: t xi1 xi2.
- move=> > /= ?. by congr var.
- move=> ? IH1 ? IH2 ?? Hxi /=. congr app; [by apply: IH1 | by apply: IH2].
- move=> ? IH > Hxi /=. congr lam. apply: IH.
case; first done. move=> ?. by congr S.
Qed.
Lemma ext_subst_term sigma1 sigma2 t : (forall n, sigma1 n = sigma2 n) ->
subst sigma1 t = subst sigma2 t.
Proof.
elim: t sigma1 sigma2.
- by move=> > /= ?.
- move=> ? IH1 ? IH2 ?? Hsigma /=. congr app; [by apply: IH1 | by apply: IH2].
- move=> ? IH > Hsigma /=. congr lam. apply: IH.
case; first done. move=> ?. by rewrite /= Hsigma.
Qed.
Lemma ren_ren_term xi1 xi2 t : ren xi2 (ren xi1 t) = ren (funcomp xi2 xi1) t.
Proof.
elim: t xi1 xi2 => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_ren_term. by case.
Qed.
Lemma ren_as_subst_term xi t : ren xi t = subst (funcomp var xi) t.
Proof.
elim: t xi => /=.
- done.
- move=> ? IH1 ? IH2 ?. by rewrite IH1 IH2.
- move=> ? IH ?. rewrite IH.
congr lam. apply: ext_subst_term. by case.
Qed.
Lemma ren_subst_term xi sigma t : ren xi (subst sigma t) = subst (funcomp (ren xi) sigma) t.
Proof.
elim: t xi sigma => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_subst_term.
case; first done. move=> ?. by rewrite /= !ren_ren_term.
Qed.
Lemma subst_ren_term xi sigma t : subst sigma (ren xi t) = subst (funcomp sigma xi) t.
Proof.
elim: t xi sigma => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_subst_term. by case.
Qed.
Lemma subst_subst_term sigma1 sigma2 t : subst sigma2 (subst sigma1 t) = subst (funcomp (subst sigma2) sigma1) t.
Proof.
elim: t sigma1 sigma2 => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_subst_term.
case; first done. move=> ?.
by rewrite /= !ren_subst_term !subst_ren_term.
Qed.
Lemma subst_var_term s : subst var s = s.
Proof.
elim: s.
- done.
- move=> ? IH1 ? IH2 /=. by rewrite IH1 IH2.
- move=> ? IH /=. congr lam. rewrite -[RHS]IH.
apply: ext_subst_term. by case.
Qed.
Definition simpl_term := (ren_ren_term, ren_subst_term, subst_ren_term, subst_subst_term, subst_var_term).
Lemma boundE k s : bound k s ->
match s with
| var n => k > n
| app s t => bound k s /\ bound k t
| lam s => bound (S k) s
end.
Proof. by case. Qed.
Lemma bound_ext_subst_term {k sigma1 sigma2 s} : bound k s -> (forall n, n < k -> sigma1 n = sigma2 n) ->
subst sigma1 s = subst sigma2 s.
Proof.
elim: s k sigma1 sigma2.
- move=> > /boundE /= ?. by apply.
- move=> ? IH1 ? IH2 k sigma1 sigma2 /boundE + ? /=.
move=> [/IH1] => /(_ sigma1 sigma2) ->; first done.
by move=> /IH2 => /(_ sigma1 sigma2) ->.
- move=> ? IH k sigma1 sigma2 /boundE /IH {}IH H /=. congr lam.
apply: IH.
move=> [|n]; first done.
move=> /= ?. rewrite H; [lia|done].
Qed.
Lemma subst_closed {sigma t} : closed t -> subst sigma t = t.
Proof.
move=> /closed_dcl /bound_ext_subst_term.
rewrite -[RHS]subst_var_term. apply. lia.
Qed.
Lemma ren_closed {xi t} : closed t -> ren xi t = t.
Proof. rewrite ren_as_subst_term. by apply: subst_closed. Qed.
Lemma L_subst_wCBN_subst s k t :
closed t -> L.subst s k t = subst (fun n => if Nat.eqb n k then t else var n) s.
Proof.
move=> Ht. elim: s k.
- done.
- move=> ? IH1 ? IH2 ? /=. by rewrite IH1 IH2.
- move=> ? IH k /=. rewrite IH.
congr lam. apply: ext_subst_term.
move=> [|n] /=; first done.
case: (Nat.eqb n k); last done.
by rewrite (ren_closed Ht).
Qed.
Lemma bound_ren {k k' xi t} : bound k t -> (forall n, n < k -> xi n < k') -> bound k' (ren xi t).
Proof.
elim: t k k' xi.
- move=> > /boundE ? H /=. apply: dclvar. by apply: H.
- move=> ? IH1 ? IH2 > /boundE + ? /=.
move=> [/IH1 {}IH1 /IH2 {}IH2]. apply: dclApp; [by apply: IH1|by apply: IH2].
- move=> ? IH > /boundE /IH {}IH H /=.
apply: dcllam. apply: IH.
move=> [|n] /=; [|have := H n]; lia.
Qed.
Lemma bound_subst {k k' sigma t} : bound k t -> (forall n, n < k -> bound k' (sigma n)) -> bound k' (subst sigma t).
Proof.
elim: t k k' sigma.
- move=> > /boundE ? H /=. by apply: H.
- move=> ? IH1 ? IH2 > /boundE + ? /=.
move=> [/IH1 {}IH1 /IH2 {}IH2]. apply: dclApp; [by apply: IH1|by apply: IH2].
- move=> ? IH > /boundE /IH {}IH H /=.
apply: dcllam. apply: IH.
move=> [|n] /=.
+ move=> _. apply: dclvar. lia.
+ move=> ?. apply: bound_ren; [apply: H|]; lia.
Qed.
Lemma not_closed_var n : closed (var n) -> False.
Proof. move=> /(_ n (lam (var 0))) /=. by rewrite Nat.eqb_refl. Qed.
Lemma closed_I s : (forall k, L.subst s k (lam (var 0)) = s) -> closed s.
Proof.
move=> H k u. elim: s k u {H}(H k).
- move=> /=. move=> n k u. by case: (Nat.eqb n k).
- by move=> ? IH1 ? IH2 k ? /= [/IH1 -> /IH2 ->].
- by move=> ? IH k ? /= [/IH ->].
Qed.
Import L (term, var, app, lam).
Import L_facts (closed, bound, closed_dcl, dclvar, dclApp, dcllam).
From Undecidability Require Import wCBN.
Require Import PeanoNat Lia.
Require Import ssreflect ssrbool ssrfun.
Set Default Goal Selector "!".
Lemma ext_ren_term xi1 xi2 t : (forall n, xi1 n = xi2 n) -> ren xi1 t = ren xi2 t.
Proof.
elim: t xi1 xi2.
- move=> > /= ?. by congr var.
- move=> ? IH1 ? IH2 ?? Hxi /=. congr app; [by apply: IH1 | by apply: IH2].
- move=> ? IH > Hxi /=. congr lam. apply: IH.
case; first done. move=> ?. by congr S.
Qed.
Lemma ext_subst_term sigma1 sigma2 t : (forall n, sigma1 n = sigma2 n) ->
subst sigma1 t = subst sigma2 t.
Proof.
elim: t sigma1 sigma2.
- by move=> > /= ?.
- move=> ? IH1 ? IH2 ?? Hsigma /=. congr app; [by apply: IH1 | by apply: IH2].
- move=> ? IH > Hsigma /=. congr lam. apply: IH.
case; first done. move=> ?. by rewrite /= Hsigma.
Qed.
Lemma ren_ren_term xi1 xi2 t : ren xi2 (ren xi1 t) = ren (funcomp xi2 xi1) t.
Proof.
elim: t xi1 xi2 => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_ren_term. by case.
Qed.
Lemma ren_as_subst_term xi t : ren xi t = subst (funcomp var xi) t.
Proof.
elim: t xi => /=.
- done.
- move=> ? IH1 ? IH2 ?. by rewrite IH1 IH2.
- move=> ? IH ?. rewrite IH.
congr lam. apply: ext_subst_term. by case.
Qed.
Lemma ren_subst_term xi sigma t : ren xi (subst sigma t) = subst (funcomp (ren xi) sigma) t.
Proof.
elim: t xi sigma => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_subst_term.
case; first done. move=> ?. by rewrite /= !ren_ren_term.
Qed.
Lemma subst_ren_term xi sigma t : subst sigma (ren xi t) = subst (funcomp sigma xi) t.
Proof.
elim: t xi sigma => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_subst_term. by case.
Qed.
Lemma subst_subst_term sigma1 sigma2 t : subst sigma2 (subst sigma1 t) = subst (funcomp (subst sigma2) sigma1) t.
Proof.
elim: t sigma1 sigma2 => /=.
- done.
- move=> ? IH1 ? IH2 ??. by rewrite IH1 IH2.
- move=> ? IH ??. rewrite IH.
congr lam. apply: ext_subst_term.
case; first done. move=> ?.
by rewrite /= !ren_subst_term !subst_ren_term.
Qed.
Lemma subst_var_term s : subst var s = s.
Proof.
elim: s.
- done.
- move=> ? IH1 ? IH2 /=. by rewrite IH1 IH2.
- move=> ? IH /=. congr lam. rewrite -[RHS]IH.
apply: ext_subst_term. by case.
Qed.
Definition simpl_term := (ren_ren_term, ren_subst_term, subst_ren_term, subst_subst_term, subst_var_term).
Lemma boundE k s : bound k s ->
match s with
| var n => k > n
| app s t => bound k s /\ bound k t
| lam s => bound (S k) s
end.
Proof. by case. Qed.
Lemma bound_ext_subst_term {k sigma1 sigma2 s} : bound k s -> (forall n, n < k -> sigma1 n = sigma2 n) ->
subst sigma1 s = subst sigma2 s.
Proof.
elim: s k sigma1 sigma2.
- move=> > /boundE /= ?. by apply.
- move=> ? IH1 ? IH2 k sigma1 sigma2 /boundE + ? /=.
move=> [/IH1] => /(_ sigma1 sigma2) ->; first done.
by move=> /IH2 => /(_ sigma1 sigma2) ->.
- move=> ? IH k sigma1 sigma2 /boundE /IH {}IH H /=. congr lam.
apply: IH.
move=> [|n]; first done.
move=> /= ?. rewrite H; [lia|done].
Qed.
Lemma subst_closed {sigma t} : closed t -> subst sigma t = t.
Proof.
move=> /closed_dcl /bound_ext_subst_term.
rewrite -[RHS]subst_var_term. apply. lia.
Qed.
Lemma ren_closed {xi t} : closed t -> ren xi t = t.
Proof. rewrite ren_as_subst_term. by apply: subst_closed. Qed.
Lemma L_subst_wCBN_subst s k t :
closed t -> L.subst s k t = subst (fun n => if Nat.eqb n k then t else var n) s.
Proof.
move=> Ht. elim: s k.
- done.
- move=> ? IH1 ? IH2 ? /=. by rewrite IH1 IH2.
- move=> ? IH k /=. rewrite IH.
congr lam. apply: ext_subst_term.
move=> [|n] /=; first done.
case: (Nat.eqb n k); last done.
by rewrite (ren_closed Ht).
Qed.
Lemma bound_ren {k k' xi t} : bound k t -> (forall n, n < k -> xi n < k') -> bound k' (ren xi t).
Proof.
elim: t k k' xi.
- move=> > /boundE ? H /=. apply: dclvar. by apply: H.
- move=> ? IH1 ? IH2 > /boundE + ? /=.
move=> [/IH1 {}IH1 /IH2 {}IH2]. apply: dclApp; [by apply: IH1|by apply: IH2].
- move=> ? IH > /boundE /IH {}IH H /=.
apply: dcllam. apply: IH.
move=> [|n] /=; [|have := H n]; lia.
Qed.
Lemma bound_subst {k k' sigma t} : bound k t -> (forall n, n < k -> bound k' (sigma n)) -> bound k' (subst sigma t).
Proof.
elim: t k k' sigma.
- move=> > /boundE ? H /=. by apply: H.
- move=> ? IH1 ? IH2 > /boundE + ? /=.
move=> [/IH1 {}IH1 /IH2 {}IH2]. apply: dclApp; [by apply: IH1|by apply: IH2].
- move=> ? IH > /boundE /IH {}IH H /=.
apply: dcllam. apply: IH.
move=> [|n] /=.
+ move=> _. apply: dclvar. lia.
+ move=> ?. apply: bound_ren; [apply: H|]; lia.
Qed.
Lemma not_closed_var n : closed (var n) -> False.
Proof. move=> /(_ n (lam (var 0))) /=. by rewrite Nat.eqb_refl. Qed.
Lemma closed_I s : (forall k, L.subst s k (lam (var 0)) = s) -> closed s.
Proof.
move=> H k u. elim: s k u {H}(H k).
- move=> /=. move=> n k u. by case: (Nat.eqb n k).
- by move=> ? IH1 ? IH2 k ? /= [/IH1 -> /IH2 ->].
- by move=> ? IH k ? /= [/IH ->].
Qed.