将 `forall` 下的表达式上下文与 Ltac 匹配

Matching expression context under `forall` with Ltac

假设我在 Coq 中有以下定义:

Inductive Compare := Lt | Eq | Gt.

Fixpoint compare (x y : nat) : Compare :=
  match x, y with
  | 0, 0   => Eq
  | 0, S _ => Lt
  | S _, 0 => Gt
  | S x', S y' => compare x' y'
  end.

现在考虑这个引理:

Lemma foo : forall (x: nat),
    (forall z, match compare x z with
               | Lt => False
               | Eq => False
               | Gt => False
               end) -> nat -> False.
Proof.
  intros x H y.

此时证明状态如下所示:

   x : nat
   H : forall z : nat,
       match compare x z with
       | Lt => False
       | Eq => False
       | Gt => False
       end
   y : nat
   ============================
   False

我想编写 Ltac match goal 来检测:

a) 在量化假设 H

的某处,有一个假设 x : nat 用作 compare 的参数

b) 并且还有其他一些类型为 nat 的假设 - 即 y - 可用于专门化量化假设。

c) 一旦我们有了这两件事,就可以将 H 专门化为 y

我试过这样做:

 match goal with
 | [ X : nat, Y : nat
   , H : forall (z : nat), context [ compare X z ] |- _ ] => specialize (H Y)
 end.

但是这段代码至少有两处错误:

  1. forall 下使用 context 似乎是不允许的。

  2. 我想不出将 X 作为参数传递给 compare 的正确方法 在某种程度上,它被认为是作为 hypothesis.doing 存在的东西,它像这样:

这并不能完全满足您的要求,但有点接近:

match goal with
| [ X : nat, Y : nat, H : context[compare ?a _] |- _ ] =>
  match type of H with
  | forall (z: nat), _ =>
    match a with
    | X => specialize (H Y)
    end
  end
end.

但是,这不会检查 compare 的第二个参数是否与 forall 绑定的 z 相匹配。

如果要检查X是否出现在量化假设H中,只要检查它在用任何不包含[=12的值实例化后出现在H中就可以了=].例如,您可以将 H 实例化为 Y,只需将 H 的应用程序编写为 Y 的函数即可。这是我的建议:

match goal with | X : nat, H : _, Y : nat |- _ =>
  match type of (H Y) with | context[X] => specialize (H Y) end
end.

这个 Ltac 文本确实检查了 H 是一个函数。如果您想更精确地说明 H 确实应该是通用量化(或产品类型),那么您可以检查 (H Y) 的类型是否也包含 Y,如在以下片段中:

match goal with | X : nat, H : _, Y : nat |- _ =>
  match type of (H Y) with | context[X] => 
    match type of (H Y) with | context [Y] => specialize (H Y) end
  end
end.