如何逐步检查在Coq中采取哪些更复杂的策略?

时间:2019-01-05 00:12:05

标签: coq coq-tactic

我试图浏览著名而精彩的software foundations book,但我举了一个例子,其中simpl.reflexivity.仅在幕后做了很多事情,并且阻碍了我的学习和理解。

我正在经历以下定理:

Theorem plus_1_neq_0 : forall n : nat,
  beq_nat (n + 1) 0 = false. (* n+1 != 0 *)
Proof.
  intros n.
  destruct n as [| n'].
    -simpl. reflexivity.
    -simpl. reflexivity.
Qed.

我真正想要的是让我逐步了解simpl.reflexivity.所做的事情。有什么可以让我做到的吗?


Destruct应该解决以下问题:

  

因为beq_nat的第一个参数(只是not equal,即!=)进行匹配,但第一个输入取决于未知变量n和+的相同内容,因此匹配无法执行任何操作,因此simpl.会使我们陷入困境(出于某种原因)。

由于Coq后来接受了证明,因此它显然必须解决它。但是,如果仔细观察第二个目标是什么,似乎会再次引入与上述相同的问题:

2 subgoals
______________________________________(1/2)
beq_nat (0 + 1) 0 = false
______________________________________(2/2)
beq_nat (S n' + 1) 0 = false

现在我们再次将n'beq_nat都作为第一个参数。但是,对于像我这样的新手来说,+这次奇迹般地由于某种神秘的原因而工作了。我显然读过simpl. documentation,但是作为一个新手,我真的不知道自己在寻找什么,对我来说,形成浓厚的理解对我很有帮助...

无论如何,为什么它在这里起作用?我要问的原因是因为在这个示例证明中使用destruct绝不会发生,特别是simpl.重复出现一个未知变量的原因,并且似乎能够看到真正发生的事情或有所不同将很有用。因此,我认为逐步检查这些类型的事件很有用(而不是隔天发布新的SO问题)。


请注意,我确实看到了这个问题:

Step by step simplification in coq?

但是我找不到使它有用的方法,因为它是为特定示例量身定制的。希望我的问题不会局限于我的特定示例,尽管由于不知道n'(或simpl.)如何工作(或至少不知道如何工作)而逐步分解可能不会发生,上述问题的以上答案给了我这种印象)。

2 个答案:

答案 0 :(得分:3)

分解评估的一种方法是根据the question you linked的建议给simpl赋一个参数。 simpl f仅允许简化在对f的调用下出现的子表达式。在这种情况下,simpl Nat.add(或simpl plussimpl "+")将S n' + 1简化为S (n' + 1)。然后simpl beq_natbeq_nat (S (n' + 1)) 0变成false

对于reflexivity,它可以得出比较之下的两个术语是否相等,直到简化为止,这意味着,如果我没有记错的话,您总是可以将{{1 }}。

答案 1 :(得分:2)

逐步减少此步骤:

beq_nat (S n' + 1) 0 = false

  (* Without the `+` notation, which is purely for pretty-printing: *)

beq_nat (plus (S n') 1) 0 = false

  (* by definition of plus:   plus (S n') 1 = S (plus n' 1) *)

beq_nat (S (plus n' 1)) 0 = false

  (* by definition of `beq_nat`,

     beq_nat (S (plus n' 1)) 0 =
     = match S (plus n' 1) with
       | O => ... (* unreachable *)
       | S m => match 0 with
                | O => false
                | S _ => ...
                end
       end
     = match 0 with
       | O => false
       | S _ => ...
       end
     = false
  *)

false = false