在Coq中如何重复举证策略?

Mik*_*ris 2 coq coq-tactic

我想通过添加一个定理来扩展Coq'Art中的练习6.10,该定理是:对于不是1月的所有月份,is_January将等于false。

我对月份的定义如下所示:

 Inductive month : Set :=
   | January : month
   | February : month
   | March : month
   | April : month
   | May : month
   | June : month
   | July : month
   | August : month
   | September : month
   | October : month
   | November : month
   | December : month
  .

Check month_rect.
Run Code Online (Sandbox Code Playgroud)

我对is_January的定义如下所示:

Definition is_January (m : month) : Prop :=
  match m with
  | January => True
  | other   => False
  end.
Run Code Online (Sandbox Code Playgroud)

我正在做以下测试,以证明它是正确的。

Eval compute in (is_January January).
Eval compute in (is_January December).

Theorem is_January_eq_January :
  forall m : month, m = January -> is_January m = True.
Proof.
  intros m H.
  rewrite H.
  compute; reflexivity.
Qed.
Run Code Online (Sandbox Code Playgroud)

我对这个定理的证明不是很满意。

Theorem is_January_neq_not_January :
  forall m : month, m <> January -> is_January m = False.
Proof.
  induction m.
  - contradiction.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
  - intro H; simpl; reflexivity.
Qed.
Run Code Online (Sandbox Code Playgroud)

无论如何,在Coq中是否有必要在- intro H; simpl; reflexivity.非1月份的月份重复案例证明(所以我只有两个-或类似的东西,所以我不必重复自己)?还是我只是以错误的方式完全使用了这种证明?

nob*_*ody 5

一种方法是

Theorem is_January_neq_not_January :
  forall m : month, m <> January -> is_January m = False.
Proof.
  induction m; try reflexivity.
  contradiction.
Qed.
Run Code Online (Sandbox Code Playgroud)
  • simpl是隐式的reflexivity,因此是不必要的。
  • t1 ; t2将策略应用于由策略t2所创建的所有分支t1
  • try t尝试应用策略t(顾名思义),否则将不执行任何操作t

该操作将induction像以前一样运行,然后立即reflexivity在所有分支上运行(可在&解决一月分支以外的所有分支上运行)。之后,剩下的就是那个分支,可以contradiction像以前一样解决。

对于更复杂的情况,其他可能有用的构造是

  • (t1 ; t2)这组战术t1t2
  • t1 | t2t1 || t2t1 + t2这些都对“尝试的变化t1,如果失败/不会做任何有用/ ...,做t2相反,
  • fail 显式失败(如果您要撤消/重置分支中发生的事情,这很有用)

    (作为我的一个证明的复杂示例,请考虑try (split; unfold not; intro H'; inversion H'; fail)。这试图创建多个子分支(split),希望它们都是矛盾的,并且可以通过解决inversion H'。如果不起作用,则inversions会创建一个大分支一团糟,所以它显式地fail是s,以便撤消战术链的影响。最终结果是,许多无聊的情况会自动得到解决,而有趣的情况对于手动解决仍保持不变。)

  • 以及更多–请参阅Coq参考手册的第9章(“战术语言”),以获取对这些以及许多其他有用构造的详细说明。

  • `now destruct m.`也可以解决问题-等同于`destruct m; easy.`和[`easy`](https://coq.inria.fr/library/Coq.Init.Tactics.html)策略足够聪明,可以使用“矛盾”和“反身性”。 (3认同)