Library coqrel.RDestruct
The RDestruct class
Introducing the hypothesis to be destructed
Ltac rdestruct_assert :=
lazymatch goal with
| |- _ (match ?m with _ ⇒ _ end) (match ?n with _ ⇒ _ end) ⇒
let Tm := type of m in
let Tn := type of n in
let R := fresh "R" in
evar (R: rel Tm Tn);
assert (R m n); subst R
end.
RDestruct steps
To use RDestruct instances to reduce a goal involving pattern
matching G := _ (match m with _ end) (match n with _ end), we
need to establish that m and n are related by some relation R,
then locate an instance of RDestruct that corresponds to R. It
is essential that this happens in one step. At some point, I tried
to split the process in two different RSteps, so that the user
could control the resolution of the ?R m n subgoal. However, in
situation where RDestruct is not the right strategy, this may
push a delayed rauto into a dead end. Thankfully, now we can use
the RAuto typeclass to solve the ?R m n subgoal in one swoop.
Lemma rdestruct_rstep {A B} m n (R: rel A B) P (Q: rel _ _):
RAuto (R m n) →
RDestruct R P →
P (rdestruct_result m n Q) →
Q m n.
Proof.
intros Hmn HR H.
firstorder.
Qed.
Ltac use_rdestruct_rstep m n :=
let H := fresh in
intro H;
pattern m, n;
eapply (rdestruct_rstep m n);
[ .. | eexact H].
Hint Extern 40 (RStep _ (_ (match ?m with _⇒_ end) (match ?n with _⇒_ end))) ⇒
use_rdestruct_rstep m n : typeclass_instances.
Choosing to discard or keep equations
CoInductive rdestruct_remember := rdestruct_remember_intro.
Ltac rdestruct_remember :=
lazymatch goal with
| _ : rdestruct_remember |- _ ⇒
idtac
| _ ⇒
let H := fresh "Hrdestruct" in
pose proof rdestruct_remember_intro as H
end.
Ltac rdestruct_forget :=
lazymatch goal with
| H : rdestruct_remember |- _ ⇒
clear H
| _ ⇒
idtac
end.
The following RStep instance will keep or discard the equations
in rdestruct_result based on the user's choice.
Lemma rdestruct_forget_rintro {A B} m n (Q: rel A B) x y:
RIntro (Q x y) (rdestruct_result m n Q) x y.
Proof.
firstorder.
Qed.
Lemma rdestruct_remember_rintro {A B} m n (Q: rel A B) x y:
RIntro (m = x → n = y → Q x y) (rdestruct_result m n Q) x y.
Proof.
firstorder.
Qed.
Ltac rdestruct_result_rintro :=
lazymatch goal with
| _ : rdestruct_remember |- _ ⇒
eapply rdestruct_remember_rintro
| _ ⇒
eapply rdestruct_forget_rintro
end.
Hint Extern 100 (RIntro _ (rdestruct_result _ _ _) _ _) ⇒
rdestruct_result_rintro : typeclass_instances.
Default instance
Ltac default_rdestruct :=
let m := fresh "m" in
let n := fresh "n" in
let Hmn := fresh "H" m n in
let P := fresh "P" in
let H := fresh in
intros m n Hmn P H;
revert m n Hmn;
delayed_conjunction (intros m n Hmn; destruct Hmn; delay);
pattern P;
eexact H.
Hint Extern 100 (RDestruct _ _) ⇒
default_rdestruct : typeclass_instances.
In the special case where the terms matched on the left- and
right-hand sides are identical, we want to destruct that term
instead. We accomplish this by introducing a special instance of
RDestruct for the relation eq.
Ltac eq_rdestruct :=
let m := fresh "m" in
let n := fresh "n" in
let Hmn := fresh "H" m n in
let P := fresh "P" in
let H := fresh in
intros m n Hmn P H;
revert m n Hmn;
delayed_conjunction (intros m n Hmn; destruct Hmn; destruct m; delay);
pattern P;
eexact H.
Hint Extern 99 (RDestruct eq _) ⇒
eq_rdestruct : typeclass_instances.