我使用setoid_replace
遇到了一个奇怪的情况,其中有一个表单的校对步骤:
setoid_replace (a - c + d) with b by my_tactic
以Error: No matching clauses for match goal
失败,但在为策略追加idtac
之后:
setoid_replace (a - c + d) with b by (my_tactic; idtac)
证明成功。我对idtac
的理解是它本质上是一种无操作。为什么idtac
的存在会产生影响?
这里是完整的代码。我通过Proof General使用Coq 8.4pl6。
Require Import QArith.
Open Scope Q.
Lemma rearrange_eq_r a b c d :
a == b -> b + d == a + c -> c == d.
Proof.
intro a_eq_b; rewrite a_eq_b; symmetry; now apply Qplus_inj_l with (z := b).
Qed.
Ltac rearrange :=
match goal with
| [ H : _ == _ |- _ == _ ] => apply rearrange_eq_r with (1 := H); ring
end.
Lemma test_rearrange a b c d e (H0 : e < b) (H1 : b + c == a + d) : e < a - c + d.
Proof.
(* Why is the extra 'idtac' required in the line below? *)
setoid_replace (a - c + d) with b by (rearrange; idtac).
assumption.
Qed.
注意:正如Matt观察到的那样,idtac
似乎并不特别:似乎可以使用任何策略(包括fail
!)代替idtac
使证明成功。
答案 0 :(得分:2)
感谢Jason Gross对Coq bug追踪器的解释。这与Ltac战术语言中的评估顺序有关。在失败的情况下,rearrange
中的匹配被应用于直接目标中的不等式,而不是setoid_replace
生成的等式。这是Jason对错误报告的回应:
这是因为在[setoid_replace]之前评估了[match] 运行。这是Ltac不幸遭遇的事情之一 像[match]和[let ... in ...]一样急切地评估直到a 带分号的语句,或其他不匹配的非let-in语句 到达。如果你添加[idtac; ]在[重新排列]中的[匹配]之前,你的 问题就会消失。