您需要证明给定自然数a
只有三种情况。任一a
为0,无论是a
是另一数目k
和k < a
双,或a
是双k
+ 1和k < a
,即这三种情况是独占(这是重要的,否则使得模式匹配可能会导致一个inconistency) 。
幸运的是,所有这些都可以完成。这是一个先进的Coq编程,但它已在ZArith
中完成。这是一个解决方案。
首先注意到另一个数字已经由Coq库中的一个函数div2
提供。
Require Import Arith Nat.
Definition cases_div2 (a : nat) :
{k : nat | a = 2 * k /\ k < a}+{k : nat | a = S (2 * k) /\ k < a}+{a=0}.
destruct a as [ | a'].
right; reflexivity.
case_eq (odd (S a')); intros odd_a.
left; right; exists (div2 (S a')); rewrite (div2_odd (S a')) at 1.
split.
rewrite odd_a; simpl b2n; ring.
apply lt_div2; auto with arith.
left; left; exists (div2 (S a')); rewrite (div2_odd (S a')) at 1.
split.
rewrite odd_a; simpl b2n; ring.
apply lt_div2; auto with arith.
Defined.
现在,你可以在你的电话号码模式匹配一个使用cases_div2
,但仍不足以定义函数,因为递归使用Fixpoint
依靠递归调用发生在前作,这里k
不能写作为前任模式,可用于任何输入a
。你需要更强大的递归。我通常依靠Function
或Fix
进行这种强递归。这里是Fix
Definition sum_of_halves : nat -> nat :=
Fix Arith.Wf_nat.lt_wf (fun _ => nat)
(fun a (sum_of_halves' : forall y, y < a -> nat) =>
match cases_div2 a with
| inright h => 0
| inleft (inl (exist _ k (conj keq klt))) =>
a + sum_of_halves' k klt
| inleft (inr (exist _ k (conj keq klt))) =>
a + sum_of_halves' k klt
end).
一个例子然后来思考sum_of_halves
你需要充分的理由归纳推理的,并使用Fix_eq
。
这是一种可能性。
有很多讨论这个问题,使用搜索功能! – ejgallego
我搜索偶数,奇数或两者的模式匹配。我找不到任何足够的答案来回答我的问题。 – MoronicAcid