*中有像应用lem一样的东西吗?

时间:2019-02-18 04:37:07

标签: coq

是否有办法为场所中的每个可能的H调用apply lem in H,例如rewrite lem in *

Axiom P Q : nat -> Prop.
Axiom lem : forall (n : nat), P n -> Q n.
Goal P O -> P (S O) -> True.
  intros. apply lem in H. apply lem in H0.

1 个答案:

答案 0 :(得分:0)

我找不到内置的任何内容,但是可以用Ltac编写这样的策略。

首先,是特殊情况。

Axiom P Q : nat -> Prop.
Axiom lem : forall (n : nat), P n -> Q n.
Goal P O -> P (S O) -> True.
  intros.
  repeat match goal with
    x : _ |- _ => apply lem in x
  end.
Abort.

现在我们可以对此进行概括

Ltac apply_in_premises t :=
  repeat match goal with
    x : _ |- _ => apply t in x
  end.

并像这样使用它:

Goal P O -> P (S O) -> True.
  intros.
  apply_in_premises lem.
Abort.

不幸的是,如果应用lem会产生其他可以应用lem的东西,则这种方法会导致无限循环。

Axiom P : nat -> Prop.
Axiom lem : forall (n : nat), P n -> P (S n).
Ltac apply_in_premises t :=
  repeat match goal with
    x : _ |- _ => apply t in x
  end.

Goal P O -> P (S O) -> nat -> True.
  intros.
  apply_in_premises lem. (* infinite loop *)
Abort.

如果您对此感到担心,则可以在注释中使用Yves建议的变体。只需将apply t in x更改为apply t in x; revert x将确保不会再次匹配该假设。但是,最终结果将具有目标中的所有假设,例如P -> G,而不是以p: P为前提,以G为目标。

要自动重新intro得出这些假设,我们可以跟踪假设已还原多少次,然后再次引入它们。

Ltac intro_n n :=
  match n with
  | 0 => idtac
  | S ?n' => intro; intro_n n'
  end.

Ltac apply_in_premises_n t n :=
  match goal with
  | x : _ |- _ => apply t in x; revert x;
                  apply_in_premises_n t (S n)
  | _ => intro_n n (* now intro all the premises that were reverted *)
  end.

Tactic Notation "apply_in_premises" uconstr(t) := apply_in_premises_n t 0.

Axiom P : nat -> Prop.
Axiom lem : forall (n : nat), P n -> P (S n).

Goal P O -> P (S O) -> nat -> True.
  intros.
  apply_in_premises lem. (* only applies `lem` once in each of the premises *)
Abort.

在这里,策略intro_n n适用intro n次。

我一般没有对此进行测试,但是在上述情况下效果很好。如果无法还原假设(例如,如果其他假设依赖于假设),则可能会失败。它也可能会重新排列假设,因为重新引入已恢复的假设时,该假设将被置于假设列表的末尾。