假设我们正试图将某些(半)群理论属性形式化,如下所示:
Section Group.
Variable A: Type.
Variable op: A -> A -> A.
Definition is_left_neutral (e: A) := forall x: A, (op e x) = x.
Definition is_right_neutral (e: A) := forall x: A, x = (op x e).
Lemma uniqueness_of_neutral:
forall a b: A, (is_left_neutral a) -> (is_right_neutral b) -> (a = b).
Proof.
intro; intro.
intros lna rnb.
elim lna with b; elim rnb with a.
reflexivity.
Qed.
End Group.
如果我们颠倒上述任一定义中的等式,即用
替换定义,它的工作正常,但Definition is_left_neutral (e: A) := forall x: A, x = (op e x).
和
Definition is_right_neutral (e: A) := forall x: A, (op x e) = x.
分别在reflexivity
处证明失败,因为elim
个应用程序中的一个或两个都不执行任何操作。
当然有一个基于assert
的解决方法,但是那太多的努力而且简直烦人......
为什么所涉及的Coq战术(elim
,case
等)对订单如此敏感?我想,它不应该明显减慢战术(<<<<<<<<<<<&#2)。
有没有办法让他们在需要的时候自动应用symmetry
,而不必每次都打扰我?在手册中找不到这个问题。
答案 0 :(得分:5)
首先,使用elim
来操纵相等是很麻烦的。以下是我使用rewrite
编写校样以及更改is_left_neutral
的定义的方法。
Section Group.
Variable A: Type.
Variable op: A -> A -> A.
Definition is_left_neutral (e: A) := forall x: A, op e x = x.
Definition is_right_neutral (e: A) := forall x: A, op x e = x.
Lemma uniqueness_of_neutral:
forall a b: A, is_left_neutral a -> is_right_neutral b -> a = b.
Proof.
intros a b lna rnb.
now rewrite <- (lna b), rnb.
Qed.
End Group.
注意第一次重写中的<-
:它告诉Coq从左到右从右到左的insead重写。使用elim
时,基本上只能在一个方向(从右到左)重写,这会导致您看到的行为。
我现在无法想到只在重写策略中尝试一个方向的原因,但我认为这不是出于性能原因。在任何情况下,您都可以定义自己的rewrite
变体,它会尝试从左到右重写,然后从右到左重写,如果这不起作用:
Section Group.
Variable A: Type.
Variable op: A -> A -> A.
Definition is_left_neutral (e: A) := forall x: A, op e x = x.
Definition is_right_neutral (e: A) := forall x: A, op x e = x.
Ltac my_rewrite t :=
first [ rewrite t | rewrite <- t ].
Lemma uniqueness_of_neutral:
forall a b: A, is_left_neutral a -> is_right_neutral b -> a = b.
Proof.
intros a b lna rnb.
now my_rewrite (lna b); my_rewrite rnb.
Qed.
End Group.