我正在尝试编写一种策略,该策略将自动解决基于Setoid
的假设中的不一致之处。
例如,如果我有以下假设,
H1 : x == y
H2 : z == y
H3 : x =/= z
我希望能够使用exfalso
,apply
,transitivity
和symmetry
的某种组合来解决此问题。使用这种策略时:
match goal with
[ eq1 : ?X == ?Z |- _ ] =>
match goal with
[ eq2 : ?Y == ?Z |- _ ] =>
match goal with
[ eq3 : ?X =/= ?Y |- _ ] => exfalso; apply eq3; [...]
end
end
end.
eq1
和eq2
将绑定到相同的假设。有什么方法可以确保将?X
和?Y
统一为不同的变量?
答案 0 :(得分:2)
我认为eq1
和eq2
受同一个假设约束的事实不是问题,因为match
在选择失败的分支时会回溯。这是一个实现类似目标的证明,用莱布尼兹相等性代替了类固醇相等性:
Lemma test T (x y z : T) : x = y -> z = y -> x <> z -> False.
Proof.
intros.
match goal with
| eq1 : ?X = ?Y |- _ =>
match goal with
| eq2 : ?Z = ?Y |- _ =>
match goal with
| eq3 : ?X <> ?Z |- _ => destruct (eq3 (eq_trans eq1 (eq_sym eq2)))
end
end
end.
Qed.
请注意,这也可以写成更紧凑的形式:
Lemma test T (x y z : T) : x = y -> z = y -> x <> z -> False.
Proof.
intros.
match goal with
| eq1 : ?X = ?Y,
eq2 : ?Z = ?Y,
eq3 : ?X <> ?Z |- _ => destruct (eq3 (eq_trans eq1 (eq_sym eq2)))
end.
Qed.
修改
如果您绝对希望尽早防止重叠的比赛,也可以使用fail
策略来强制回溯:
Lemma test T (x y z : T) : x = y -> z = y -> False.
Proof.
intros.
match goal with
| eq1 : ?X = ?Y |- _ =>
match goal with
| eq2 : ?Z = Y |- _ =>
match Z with
| X => fail 1
| _ => idtac eq1 eq2
end
end
end.
Abort.
如果Coq将eq1
和eq2
绑定到相同的假设,则第三个match
的第一个分支将被激活并调用fail 1
。这样的效果是选择了倒数第二个回溯点中的下一个分支-在本例中为 second match
,该分支绑定了eq2
。运行此代码将在响应缓冲区中打印两个不同的假设名称。
(如果将fail 1
替换为fail 0
(或简单地替换为fail
),则Coq会选择最近的回溯点的下一个分支,即第三个match
。由于下一个分支接受所有值,所以无论如何它将运行idtac eq1 eq2
,这在我的机器上最终将打印H0 H0
。)
请注意,在您的示例中,您可能还同时匹配了eq1
和eq2
以防止它们相等。例如,以下试图强制这种相等的代码片段失败了:
Lemma test T (x y z : T) : x = y -> z = y -> False.
Proof.
intros.
match goal with
| eq1 : ?X = ?Y,
eq2 : ?Z = ?Y |- _ =>
match Z with
| X => idtac eq1 eq2
end
end.
Abort.
(* Error: No matching clauses for match. *)