模式匹配偶数和奇数案例

时间:2017-09-23 19:27:28

标签: coq

假设我在Coq中编写了一个Fixpoint算法,它总结了所有"一半"一个数字:

Fixpoint sum_of_halves (a : nat) : nat :=
  match a with
  | 0 => 0
  | 2 * k => a + (sum_of_halves k)
  | S (2 * k)  => a + (sum_of_halves k)
  end.

尝试评估算法会得到:Error: Invalid notation for pattern.

如何让Coq识别a是偶数还是奇数,并将其与2 * kS (2 * k)匹配?

2 个答案:

答案 0 :(得分:2)

Coq只能在构造函数上matchnat有两个构造函数OS,因此您无法在2 * k上匹配。您必须使用非match构造或非nat类型或不同的算法。

答案 1 :(得分:0)

您需要证明给定自然数a只有三种情况。 a为0,a为另一个数字kk < a的两倍,或a为双k + 1且k < a,这三种情况都是排他性的(这很重要,否则使模式匹配成为可能会导致不一致)。

幸运的是,所有这一切都可以完成。这是一个有点高级的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对您的数字a进行模式匹配,但仍然不足以定义您的函数,因为使用Fixpoint的递归依赖于在前任上发生的递归调用,而这里k不能写为适用于任何输入a的前趋模式。你需要一种更强大的递归。我通常依靠FunctionFix来进行这种强大的递归。以下是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

这是一种可能性。