我试图浏览著名而精彩的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.
)如何工作(或至少不知道如何工作)而逐步分解可能不会发生,上述问题的以上答案给了我这种印象)。
答案 0 :(得分:3)
分解评估的一种方法是根据the question you linked的建议给simpl
赋一个参数。 simpl f
仅允许简化在对f
的调用下出现的子表达式。在这种情况下,simpl Nat.add
(或simpl plus
或simpl "+"
)将S n' + 1
简化为S (n' + 1)
。然后simpl beq_nat
将beq_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