Autosubst.Autosubst_Tactics
The main automation tactics.
Derived substitution lemmas.
Section LemmasForSubst.
Context {term : Type} {Ids_term : Ids term}
{Rename_term : Rename term} {Subst_term : Subst term}
{SubstLemmas_term : SubstLemmas term}.
Implicit Types (s t : term) (sigma tau theta : var -> term) (xi : var -> var).
Lemma rename_substX xi : rename xi = subst (ren xi).
Proof. f_ext. apply rename_subst. Qed.
Lemma upX sigma : up sigma = ids 0 .: sigma >>> subst (ren (+1)).
Proof. unfold up. now rewrite rename_substX. Qed.
Lemma id_scompX sigma : ids >>> subst sigma = sigma.
Proof. f_ext. apply id_subst. Qed.
Lemma id_scompR {A} sigma (f : _ -> A) :
ids >>> (subst sigma >>> f) = sigma >>> f.
Proof. now rewrite <- compA, id_scompX. Qed.
Lemma subst_idX : subst ids = id.
Proof. f_ext. exact subst_id. Qed.
Lemma subst_compI sigma tau s :
s.[sigma].[tau] = s.[sigma >>> subst tau].
Proof. apply subst_comp. Qed.
Lemma subst_compX sigma tau :
subst sigma >>> subst tau = subst (sigma >>> subst tau).
Proof. f_ext. apply subst_comp. Qed.
Lemma subst_compR {A} sigma tau (f : _ -> A) :
subst sigma >>> (subst tau >>> f) = subst (sigma >>> subst tau) >>> f.
Proof. now rewrite <- subst_compX. Qed.
Lemma fold_ren_cons (x : var) (xi : var -> var) :
ids x .: ren xi = ren (x .: xi).
Proof. unfold ren. now rewrite scons_comp. Qed.
Lemma upE sigma : up sigma = ids 0 .: sigma >> ren (+1).
Proof. apply upX. Qed.
(* unfold upn *)
Lemma upnSX n sigma :
upn (S n) sigma = ids 0 .: upn n sigma >>> subst (ren (+1)).
Proof.
unfold iterate; now rewrite upX.
Qed.
Lemma upnSE n sigma :
upn (S n) sigma = ids 0 .: upn n sigma >> ren (+1).
Proof.
now rewrite upnSX.
Qed.
Lemma upn0 sigma : upn 0 sigma = sigma.
Proof. reflexivity. Qed.
(* fold up *)
Lemma fold_up k sigma :
ids k .: sigma >> ren (+S k) = up sigma >> ren (+k).
Proof.
unfold scomp, ren. rewrite upX; fsimpl; rewrite id_subst, subst_compX; simpl; fsimpl.
unfold ren. fsimpl. rewrite id_scompX. now fsimpl.
Qed.
Lemma fold_up0 sigma :
sigma >> ren (+0) = sigma.
Proof.
unfold scomp, ren. fsimpl. now rewrite subst_idX.
Qed.
(* combine up *)
Lemma fold_up_up sigma : up (up sigma) = upn 2 sigma.
Proof. reflexivity. Qed.
Lemma fold_up_upn n sigma : up (upn n sigma) = upn (S n) sigma.
Proof. reflexivity. Qed.
Lemma fold_upn_up n sigma : upn n (up sigma) = upn (S n) sigma.
Proof. now rewrite iterate_Sr. Qed.
End LemmasForSubst.
Derived substitution lemmas for heterogeneous substitutions.
Section LemmasForHSubst.
Context {inner outer : Type}.
Context {Ids_inner : Ids inner} {Rename_inner : Rename inner}
{Subst_inner : Subst inner} {SubstLemmas_inner : SubstLemmas inner}.
Context {Ids_outer : Ids outer} {Rename_outer : Rename outer}
{Subst_outer : Subst outer} {SubstLemmas_outer : SubstLemmas outer}.
Context {HSubst_inner_outer : HSubst inner outer}.
Context {HSubstLemmas_inner_outer : HSubstLemmas inner outer}.
Context {SubstHSubstComp_inner_outer : SubstHSubstComp inner outer}.
Lemma id_hsubstX (sigma : var -> inner) : ids >>> hsubst sigma = ids.
Proof. f_ext. apply id_hsubst. Qed.
Lemma id_hsubstR {A} (f : _ -> A) (sigma : var -> inner) :
ids >>> (hsubst sigma >>> f) = ids >>> f.
Proof. now rewrite <- compA, id_hsubstX. Qed.
Lemma hsubst_idX : hsubst ids = id.
Proof. f_ext. exact hsubst_id. Qed.
Lemma hsubst_compI sigma tau s :
s.|[sigma].|[tau] = s.|[sigma >>> subst tau].
Proof. apply hsubst_comp. Qed.
Lemma hsubst_compX sigma tau :
hsubst sigma >>> hsubst tau = hsubst (sigma >>> subst tau).
Proof. f_ext. apply hsubst_comp. Qed.
Lemma hsubst_compR {A} sigma tau (f : _ -> A) :
hsubst sigma >>> (hsubst tau >>> f) = hsubst (sigma >>> subst tau) >>> f.
Proof. now rewrite <- hsubst_compX. Qed.
Lemma scomp_hcompI sigma theta s :
s.[sigma].|[theta] = s.|[theta].[sigma >>> hsubst theta].
Proof. apply subst_hsubst_comp. Qed.
Lemma scomp_hcompX sigma theta :
subst sigma >>> hsubst theta = hsubst theta >>> subst (sigma >>>hsubst theta).
Proof. f_ext. apply subst_hsubst_comp. Qed.
Lemma scomp_hcompR {A} sigma theta (f : _ -> A) :
subst sigma >>> (hsubst theta >>> f) =
hsubst theta >>> (subst (sigma >>> hsubst theta) >>> f).
Proof. now rewrite <- compA, scomp_hcompX. Qed.
End LemmasForHSubst.
Normalize the goal state.
Ltac autosubst_typeclass_normalize :=
mmap_typeclass_normalize;
repeat match goal with
| [|- context[ids ?x]] =>
let s := constr:(ids x) in progress change (ids x) with s
| [|- appcontext[ren ?xi]] =>
let s := constr:(ren xi) in progress change (ren xi) with s
| [|- appcontext[rename ?xi]] =>
let s := constr:(rename xi) in progress change (rename xi) with s
| [|- appcontext[subst ?sigma]] =>
let s := constr:(subst sigma) in progress change (subst sigma) with s
| [|- appcontext[hsubst ?sigma]] =>
let s := constr:(hsubst sigma) in progress change (hsubst sigma) with s
end.
Ltac autosubst_typeclass_normalizeH H :=
mmap_typeclass_normalizeH H;
repeat match typeof H with
| context[ids ?x] =>
let s := constr:(ids x) in progress change (ids x) with s in H
| appcontext[ren ?xi] =>
let s := constr:(ren xi) in progress change (ren xi) with s in H
| appcontext[rename ?xi] =>
let s := constr:(rename xi) in progress change (rename xi) with s in H
| appcontext[subst ?sigma] =>
let s := constr:(subst sigma) in progress change (subst sigma) with s in H
| appcontext[hsubst ?sigma] =>
let s := constr:(hsubst sigma) in progress change (hsubst sigma) with s in H
end.
Ltac autosubst_unfold_up :=
rewrite ?upX, ?upnSX;
repeat match goal with
| [|- context[upn 0 ?sigma]] => change (upn 0 sigma) with sigma
end.
Ltac autosubst_unfold_upH H :=
rewrite ?upX, ?upnSX in H;
repeat match typeof H with
| context[upn 0 ?sigma] => change (upn 0 sigma) with sigma
end.
Ltac autosubst_unfold :=
autosubst_typeclass_normalize; autosubst_unfold_up;
rewrite ?rename_substX; unfold ren, scomp, hcomp, upren.
Ltac autosubst_unfoldH H :=
autosubst_typeclass_normalizeH H; autosubst_unfold_upH H;
rewrite ?rename_substX in H; unfold ren, scomp, hcomp, upren in H.
Simplify results.
Ltac fold_ren :=
repeat match goal with
| [|- context[?xi >>> (@ids ?T _)]] =>
change (xi >>> (@ids T _)) with (@ren T _ xi)
| [|- context[?xi >>> (@ids ?T _ >>> ?g)]] =>
change (xi >>> (@ids T _ >>> g)) with (@ren T _ xi >>> g)
| [|- context[?xi >>> @ren ?T _ ?zeta]] =>
change (xi >>> @ren T _ zeta) with (@ren T _ (xi >>> zeta))
| [|- context[?xi >>> (@ren ?T _ ?zeta >>> ?g)]] =>
change (xi >>> (@ren T _ zeta >>> g)) with
(@ren T _ (xi >>> zeta) >>> g)
| [|- context [ids ?x .: ?sigma]] =>
first[
rewrite fold_ren_cons
| replace (ids x .: ids) with (ren (x .: id))
by (symmetry; apply fold_ren_cons)
]
end.
Ltac fold_renH H :=
repeat match typeof H with
| context[?xi >>> (@ids ?T _)] =>
change (xi >>> (@ids T _)) with (@ren T _ xi) in H
| context[?xi >>> (@ids ?T _ >>> ?g)] =>
change (xi >>> (@ids T _ >>> g)) with (@ren T _ xi >>> g) in H
| context[?xi >>> @ren ?T _ ?zeta] =>
change (xi >>> @ren T _ zeta) with (@ren T _ (xi >>> zeta)) in H
| context[?xi >>> (@ren ?T _ ?zeta >>> ?g)] =>
change (xi >>> (@ren T _ zeta >>> g)) with
(@ren T _ (xi >>> zeta) >>> g) in H
| context [ids ?x .: ?sigma] =>
first[
rewrite fold_ren_cons in H
| replace (ids x .: ids) with (ren (x .: id)) in H
by (symmetry; apply fold_ren_cons)
]
end.
Ltac fold_comp :=
repeat match goal with
| [|- context[?f >>> (?g >>> ?h)]] =>
change (f >>> (g >>> h)) with ((f >>> g) >>> h)
| [|- context[?sigma >>> subst ?tau]] =>
change (sigma >>> subst tau) with (sigma >> tau)
| [|- context[?sigma >>> hsubst ?tau]] =>
change (sigma >>> hsubst tau) with (sigma >>| tau)
end.
Ltac fold_compH H :=
repeat match typeof H with
| context[?f >>> (?g >>> ?h)] =>
change (f >>> (g >>> h)) with ((f >>> g) >>> h) in H
| context[?sigma >>> subst ?tau] =>
change (sigma >>> subst tau) with (sigma >> tau) in H
| context[?sigma >>> hsubst ?tau] =>
change (sigma >>> hsubst tau) with (sigma >>| tau) in H
end.
Ltac fold_up := rewrite ?fold_up, ?fold_up0;
repeat match goal with
| [|- context[up (up ?sigma)]] =>
change (up (up sigma)) with (upn 2 sigma)
| [|- context[up (upn ?n ?sigma)]] =>
change (up (upn n sigma)) with (upn (S n) sigma)
| _ => rewrite fold_upn_up
end;
repeat open_fold (upren _).
Ltac fold_upH H := rewrite ?fold_up, ?fold_up0 in H;
repeat match typeof H with
| context[up (up ?sigma)] =>
change (up (up sigma)) with (upn 2 sigma) in H
| context[up (upn ?n ?sigma)] =>
change (up (upn n sigma)) with (upn (S n) sigma) in H
| _ => rewrite fold_upn_up in H
end;
repeat open_fold (upren _) in H.
Solve & Simplify goals involving substitutions.
Ltac autosubst :=
cbn; trivial; autosubst_unfold; solve [repeat first
[ solve [trivial]
| progress (
cbn; unfold _bind, ren, scomp, hcomp; fsimpl; autosubst_unfold_up;
autorewrite with autosubst;
rewrite ?id_scompX, ?id_scompR, ?subst_idX, ?subst_compX,
?subst_compR, ?id_subst, ?subst_id, ?subst_compI,
?id_hsubstX, ?id_hsubstR, ?hsubst_idX, ?scomp_hcompX,
?scomp_hcompR, ?hsubst_compX, ?hsubst_compR,
?hsubst_id, ?id_hsubst, ?hsubst_compI, ?scomp_hcompI
)
| match goal with [|- appcontext[(_ .: _) ?x]] =>
match goal with [y : _ |- _ ] => unify y x; destruct x; simpl @scons end
end
| fold_id]].
Ltac asimpl :=
autorewrite with autosubst;
cbn; autosubst_unfold; repeat first
[ progress (
cbn; unfold _bind, ren, scomp, hcomp; fsimpl; autosubst_unfold_up;
autorewrite with autosubst;
rewrite ?id_scompX, ?id_scompR, ?subst_idX, ?subst_compX,
?subst_compR, ?id_subst, ?subst_id, ?subst_compI,
?id_hsubstX, ?id_hsubstR, ?hsubst_idX, ?scomp_hcompX,
?scomp_hcompR, ?hsubst_compX, ?hsubst_compR,
?hsubst_id, ?id_hsubst, ?hsubst_compI, ?scomp_hcompI
)
| fold_id];
fold_ren; fold_comp; fold_up.
Ltac asimplH H :=
autorewrite with autosubst in H;
cbn in H; autosubst_unfoldH H; repeat first
[ progress (
cbn in H; unfold _bind, ren, scomp, hcomp in H; fsimpl in H;
autosubst_unfold_upH H; autorewrite with autosubst in H;
rewrite ?id_scompX, ?id_scompR, ?subst_idX, ?subst_compX,
?subst_compR, ?id_subst, ?subst_id, ?subst_compI,
?id_hsubstX, ?id_hsubstR, ?hsubst_idX, ?scomp_hcompX,
?scomp_hcompR, ?hsubst_compX, ?hsubst_compR,
?hsubst_id, ?id_hsubst, ?hsubst_compI, ?scomp_hcompI in H
)
| fold_id in H];
fold_renH H; fold_compH H; fold_upH H.
Tactic Notation "asimpl" "in" ident(H) := asimplH H.
Tactic Notation "asimpl" "in" "*" := (in_all asimplH); asimpl.
(* Local Variables: *)
(* coq-load-path: (("." "Autosubst")) *)
(* End: *)