在数学方面,我们经常按如下方式进行:"现在让我们考虑两种情况,k
可以是even
或odd
。对于even
案例,我们可以说exists k', 2k' = k
..."
通过将其分解为几个可用于重建原始集合的析取子集,扩展到推理整个对象集合的一般概念。
考虑到我们并不总是假设这是我们想要解构的子集之一,这个推理原理是如何在coq中捕获的?
考虑以下示例进行演示:
forall n, Nat.Even n => P n.
在这里,我们可以自然地在inversion
上Nat.Even n
获取n = 2*x
(以及n = 2*x + 1
的自动错误消除假设。但是,假设我们有以下内容:
forall n, P n
我如何声明:"让我们考虑even n
和odd n
s"。我是否需要首先证明我们有可判定的forall n : nat, even n \/ odd n
?也就是说,引入一个列出所有必需子集的新(局部或全局)引理?什么是最佳实践?
答案 0 :(得分:2)
事实上,要推断Coq中一类对象的分裂,你需要展示一个分裂它们的算法,除非你想要经典推理(这没有任何问题)。
国际海事组织,一个关键点是获得这样的可判定性假设"免费"。例如,您可以将odd : nat -> bool
实现为布尔函数,就像在某些库中完成一样,然后您可以免费获得拆分。
[编辑] 通过将相关案例作为归纳法,您可以使用一些稍微方便的模式匹配技术:
Require Import PeanoNat Nat Bool.
CoInductive parity_spec (n : nat) : Type :=
| parity_spec_odd : odd n = true -> parity_spec n
| parity_spec_even: even n = true -> parity_spec n
.
Lemma parityP n : parity_spec n.
Proof.
case (even n) eqn:H; [now right|left].
now rewrite <- Nat.negb_even, H.
Qed.
Lemma test n : even n = true \/ odd n = true.
Proof. now case (parityP n); auto. Qed.