我想有一个Ltac战术来执行Disjunction Commutavity的工作。主要是,如果我在假设P \/ Q
中某处有一个子项H
,则Ltac Com H
会将Q \/ P
作为另一个假设添加到上下文中。
我尝试通过公理提供apply
的可交换性规则;但是它仅适用于简单的假设,例如在R -> (P \/ Q)
中失败;应该添加到上下文R -> (Q \/ P)
中的位置。
答案 0 :(得分:4)
您可以使用setoid重写库,该库允许您使用除相等以外的其他关系进行重写。以下代码段显示了如何在假设中将A \/ B
替换为B \/ A
:
Require Import Setoid.
Variables A B C : Prop.
Goal ~ (A \/ B -> C).
intros H.
rewrite or_comm in H.
Abort.
要实施您想要的策略,我们只需要复制假设并重写其中即可。请注意,使用fresh
策略会生成新的假设名称。
Ltac Comm H :=
let H' := fresh "H" in
pose proof H as H';
rewrite or_comm in H'.
这里是Comm
的演示示例。
Goal ~ (A \/ B -> C).
intros H.
Comm H.
Abort.
编辑 Coq manual包含有关setoid重写的部分。粗略地说,只要您证明该假设中出现的运算与该关系兼容,就可以在假设中使用 any 关系R
进行重写。例如,如果我们将R
设为<->
,则上述重写之所以有效,是因为标准库中存在引理,表明逻辑对等受到隐含的尊重。
注意我通常建议不要让Coq名称假说本身:这些名称往往非常不稳定,通常会导致证明脚本被破坏。根据经验,如果要编写完全不涉及自动选择名称的全自动证明脚本,则应让Coq自行选择名称。这是Comm
的另一个版本,可以避免此问题。
Ltac Comm' H H' :=
pose proof H as H';
rewrite or_comm in H'.
Goal ~ (A \/ B -> C).
intros H.
Comm H H'.
Abort.