确保两个元变量未统一为同一结果

时间:2018-07-19 18:45:34

标签: coq coq-tactic

我正在尝试编写一种策略,该策略将自动解决基于Setoid的假设中的不一致之处。

例如,如果我有以下假设,

  H1 : x == y
  H2 : z == y
  H3 : x =/= z

我希望能够使用exfalsoapplytransitivitysymmetry的某种组合来解决此问题。使用这种策略时:

  match goal with
    [ eq1 : ?X == ?Z |- _ ] =>
    match goal with
      [ eq2 : ?Y == ?Z |- _ ] =>
        match goal with
          [ eq3 : ?X =/= ?Y |- _ ] => exfalso; apply eq3; [...]

        end
    end
  end.

eq1eq2将绑定到相同的假设。有什么方法可以确保将?X?Y统一为不同的变量?

1 个答案:

答案 0 :(得分:2)

我认为eq1eq2受同一个假设约束的事实不是问题,因为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将eq1eq2绑定到相同的假设,则第三个match的第一个分支将被激活并调用fail 1。这样的效果是选择了倒数第二个回溯点中的下一个分支-在本例中为 second match,该分支绑定了eq2。运行此代码将在响应缓冲区中打印两个不同的假设名称。

(如果将fail 1替换为fail 0(或简单地替换为fail),则Coq会选择最近的回溯点的下一个分支,即第三个match 。由于下一个分支接受所有值,所以无论如何它将运行idtac eq1 eq2,这在我的机器上最终将打印H0 H0。)

请注意,在您的示例中,您可能还同时匹配了eq1eq2以防止它们相等。例如,以下试图强制这种相等的代码片段失败了:

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. *)