用简单的定义
Inductive B := bb.
Inductive C := cc.
Inductive A :=
| mkA1 : B -> A
| mkA2 : C -> A.
Definition id (a: A) : A :=
match a with
| mkA1 b => mkA1 b
| mkA2 c => mkA2 c
end.
我尝试通过案例分析(破坏)来做证明,例如:
Theorem Foo :
forall a1 a2 : A , a1 <> a2 -> id a1 <> id a2.
Proof.
destruct a1; destruct a2.
Abort.
不出所料,目前的证明状态包含两个相等的子目标:
b: B
c: C
______________________________________(2/4)
mkA1 b <> mkA2 c -> id (mkA1 b) <> id (mkA2 c)
______________________________________(3/4)
mkA2 c <> mkA1 b -> id (mkA2 c) <> id (mkA1 b)
在我看来,在进行结构案例分析时,经常会出现重复的子目标。是否有一些常见的方法来删除这些重复?
我所做的是按下第二个子目标看起来像第三个:
Focus 2;
intro; apply not_eq_sym in H; apply not_eq_sym; revert H;
Unfocus.
虽然我仍无法让Coq删除重复项。现在我可以为我的第二个子目标证明一个引理,并在我的第三个子目标中重复使用它。但我想知道一些替代方案。
答案 0 :(得分:2)
以下是一些重复使用子目标的策略自动化。请注意,目标不仅必须完全匹配,而且上下文的顺序也必须匹配。在进行案例分析之前,还需要运行初始化策略。这是Coq&gt; = 8.5的代码。
Inductive B := bb.
Inductive C := cc.
Inductive A :=
| mkA1 : B -> A
| mkA2 : C -> A.
Definition id (a: A) : A :=
match a with
| mkA1 b => mkA1 b
| mkA2 c => mkA2 c
end.
Record duplicate_prod (A B : Type) := duplicate_conj { duplicate_fst : A ; duplicate_snd : B }.
Definition HERE := True.
Ltac start_remove_duplicates H :=
simple refine (let H___duplicates := @duplicate_conj _ _ I _ in _);
[ shelve | | ]; cycle 1.
Ltac find_dup H G :=
lazymatch type of H with
| duplicate_prod G _ => constr:(@duplicate_fst _ _ H)
| duplicate_prod _ _ => find_dup (@duplicate_snd _ _ H) G
end.
Ltac find_end H :=
lazymatch type of H with
| duplicate_prod _ _ => find_end (@duplicate_snd _ _ H)
| _ => H
end.
Ltac revert_until H :=
repeat lazymatch goal with
| [ H' : _ |- _ ]
=> first [ constr_eq H H'; fail 1
| revert H' ]
end.
Ltac remove_duplicates :=
[ > lazymatch goal with
| [ |- duplicate_prod _ _ ] => idtac
| [ H : duplicate_prod _ _ |- _ ]
=> generalize (I : HERE);
revert_until H;
let G := match goal with |- ?G => G end in
lazymatch type of H with
| context[duplicate_prod G]
=> let lem := find_dup H G in exact lem
| _ => let lem := find_end H in
refine (@duplicate_fst _ _ lem); clear H; (* clear to work around a bug in Coq *)
shelve
end
end.. ].
Ltac finish_duplicates :=
[ > lazymatch goal with
| [ H : duplicate_prod _ _ |- _ ] => clear H
end..
| repeat match goal with
| [ |- duplicate_prod _ ?e ]
=> split;
[ repeat lazymatch goal with
| [ |- HERE -> _ ] => fail
| _ => intro
end;
intros _
| try (is_evar e; exact I) ]
end ].
Theorem Foo :
forall a1 a2 : A , a1 <> a2 -> id a1 <> id a2.
Proof.
start_remove_duplicates.
destruct a1; destruct a2.
2:intro; apply not_eq_sym in H; apply not_eq_sym; revert c b H; intros c b.
all:remove_duplicates.
all:finish_duplicates.
这个想法是你首先要创造一个能够解决独特目标的问题。然后你做案例分析。然后你完成目标,并用evar的新投影解决它们,或者,如果你发现已经找到了你正在寻找的目标的解决方案,你可以使用该解决方案。最后,您将evar分成多个(重复数据删除)目标。还有一些额外的样板可以恢复在创建evar时不存在的假设(需要为良好类型的术语安排变量作用域),记住最初来自上下文的内容,并在最后将这些内容重新引入上下文