Coq:证明归纳关系(vs Fixpoint)

时间:2021-05-24 13:03:16

标签: coq coqide

是否可以“转换”Fixpoint 函数的count 定义:

Fixpoint count (z: Z) (l: list Z) {struct l} : nat :=
  match l with
  | nil => 0%nat
  | (z' :: l') => if (Z.eq_dec z z')
                  then S (count z l')
                  else count z l'
  end.

对于 Inductive 谓词(我第一次尝试如下,但我不确定它是否正确)? (这个谓词应该描述函数的输入输出之间的关系)

Inductive Count : nat -> list Z -> Z -> Prop :=
  | CountNil : forall (z: Z), Count 0 nil z
  | CountCons: forall (n: nat) (l0: list Z) (z: Z), Count n l0 z -> Count (S n) (cons z l0) z.

为了确定它是否正确,我定义了这个定理(弱规范):

Theorem count_correct : forall (n: nat) (z: Z) (l: list Z), Count (count z l) l z.
Proof.
  intros.
  destruct l.
  - constructor.
  - ...

但我不知道如何完成它...有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

您的关系不正确,因为它缺少列表头不是您要查找的 Z 的情况。例如。即使 Count 0 [0] 1 也没有 count 1 [0] = 0 类型的术语。添加这一点,当您使用它时,可以使类型更自然(以相同的方式对参数进行排序,并将 z 设为参数)。

Inductive Count (z : Z) : list Z -> nat -> Prop :=
  | CountNil : Count z nil 0
  | CountYes : forall l n, Count z l n -> Count z (z :: l) (S n)
  | CountNo  : forall z' l n, z <> z' -> Count z l n -> Count z (z' :: l) n.

至于正确性定理,好吧,countl 是归纳的,所以任何关于它的定理都可能如此。

Theorem count_correct (z : Z) (n : N) (l : list Z) : Count z l (count z l).
Proof.
  intros.
  induction l as [ | z' l rec].
  - constructor.
  - cbn [count].
    destruct (Z.eq_dec z z') as [<- | no]; constructor; assumption.
Qed.

请注意,有一种自动机制可以从 Count 中定义 count_correctcount

Require Import FunInd.

Function count (z : Z) (l : list Z) {struct l} : nat :=
  match l with
  | nil => 0
  | z' :: l =>
    if Z.eq_dec z z'
    then S (count z l)
    else count z l
  end.
  
Print R_count. (* Like Count *)
(* Inductive R_count (z : Z) : list Z -> nat -> Set :=
     R_count_0 : forall l : list Z, l = nil -> R_count z nil 0
  | R_count_1 : forall (l : list Z) (z' : Z) (l' : list Z),
    l = z' :: l' ->
    forall _x : z = z',
    Z.eq_dec z z' = left _x ->
    forall _res : nat,
    R_count z l' _res -> R_count z (z' :: l') (S _res)
  | R_count_2 : forall (l : list Z) (z' : Z) (l' : list Z),
    l = z' :: l' ->
    forall _x : z <> z',
    Z.eq_dec z z' = right _x ->
    forall _res : nat,
    R_count z l' _res -> R_count z (z' :: l') _res. *)
Check R_count_correct. (* : forall z l _res, _res = count z l -> R_count z l _res *)
Check R_count_complete. (* : forall z l _res, R_count z l _res -> _res = count z l *)
相关问题