Recursion Coq中的一般递归与归纳

Recursion Coq中的一般递归与归纳,recursion,coq,induction,Recursion,Coq,Induction,让我们假设我有 T型 基础良好的关系R:T->T->Prop 函数F1:T->T使参数“更小” 条件C:T->描述R“起始值”的道具 函数F2:T->T使参数“更大” 如何制作类似于以下内容的固定点: Fixpoint Example (n:T):X := match {C n} + {~C n} with left _ => ... | right _ => Example (F1 n) end. 以及我如何使“入职”(或类似)战术的以下用法成为可能:

让我们假设我有

  • T型
  • 基础良好的关系R:T->T->Prop
  • 函数F1:T->T使参数“更小”
  • 条件C:T->描述R“起始值”的道具
  • 函数F2:T->T使参数“更大”
如何制作类似于以下内容的固定点:

Fixpoint Example (n:T):X :=
  match {C n} + {~C n} with
    left _ => ... |
    right _ => Example (F1 n)
  end.
以及我如何使“入职”(或类似)战术的以下用法成为可能:

我试着用nz:{n:nat | nO}类型来实现这一点(参见《使用依赖类型进行认证编程》一书的第7.1章),但只做到了这一点:

Require Import Omega.

Definition nz: Set := {n:nat | n<>O}.
Theorem nz_t1 (n:nat): S n<>O. Proof. auto. Qed.

Definition nz_eq (n m:nz) := eq (projT1 n) (projT1 m).
Definition nz_one: nz := exist _ 1 (nz_t1 O).
Definition nz_lt (n m:nz) := lt (projT1 n) (projT1 m).

Definition nz_pred (n:nz): nz := exist _ (S (pred (pred (projT1 n)))) (nz_t1 _).

Theorem nz_Acc: forall (n:nz), Acc nz_lt n.
Proof.
 intro. destruct n as [n pn], n as [|n]. omega.
 induction n; split; intros; destruct y as [y py]; unfold nz_lt in *; simpl in *.
   omega.
   assert (y<S n\/y=S n). omega. destruct H0.
    assert (S n<>O); auto.
    assert (nz_lt (exist _ y py) (exist _ (S n) H1)). unfold nz_lt; simpl; assumption.
    fold nz_lt in *. apply Acc_inv with (exist (fun n0:nat=>n0<>O) (S n) H1). apply IHn.
    unfold nz_lt; simpl; assumption.
    rewrite <- H0 in IHn. apply IHn.
Defined.

Theorem nz_lt_wf: well_founded nz_lt. Proof. exact nz_Acc. Qed.

Lemma pred_wf: forall (n m:nz), nz_lt nz_one n -> m = nz_pred n -> nz_lt m n.
Proof.
 intros. unfold nz_lt, nz_pred in *. destruct n as [n pn], m as [m pm]. simpl in *.
 destruct n, m; try omega. simpl in *. inversion H0. omega. 
Defined.
需要导入欧米茄。
定义nz:Set:={n:nat | nO}。
定理nz_t1(n:nat):S号。证明。自动的。Qed。
定义nz_eq(nm:nz):=eq(projT1 n)(projT1 m)。
定义nz_one:nz:=exist 1(nz_t1 O)。
定义nz_lt(nm:nz):=lt(projT1 n)(projT1 m)。
定义nz_pred(n:nz):nz:=存在(pred(pred(projT1 n)))(nz_t1_)。
定理nz_Acc:forall(n:nz),Acc nz_lt n。
证明。
简介。分解n为[n pn],n为[|n]。欧米茄。
诱导n;分裂介绍;将y分解为[y-py];展开nz_lt in*;简单输入*。
欧米茄。
断言(yn0O)(sn)H1)。应用IHn。
展开nz_lt;单纯形;假设。
重写m=nz_pred n->nz_lt m n。
证明。
介绍。在*中展开nz_lt、nz_pred。析构函数n为[n pn],m为[m pm]。简单输入*。
自毁n,m;试试欧米茄。简单输入*。反转H0。欧米茄。
定义
我无法理解接下来会发生什么,因为这对我来说太复杂了


另外,在我看来,对于初学者来说,没有足够好的关于Coq中一般递归和归纳的教程。至少我能找到(

我稍后会尝试写一个更完整的答案,但是Coq有一个名为Function的命令,可以更容易地编写参数根据某种良好顺序减少的函数。请在参考手册()中查找该命令,特别是“wf”变体

Require Import Omega.

Definition nz: Set := {n:nat | n<>O}.
Theorem nz_t1 (n:nat): S n<>O. Proof. auto. Qed.

Definition nz_eq (n m:nz) := eq (projT1 n) (projT1 m).
Definition nz_one: nz := exist _ 1 (nz_t1 O).
Definition nz_lt (n m:nz) := lt (projT1 n) (projT1 m).

Definition nz_pred (n:nz): nz := exist _ (S (pred (pred (projT1 n)))) (nz_t1 _).

Theorem nz_Acc: forall (n:nz), Acc nz_lt n.
Proof.
 intro. destruct n as [n pn], n as [|n]. omega.
 induction n; split; intros; destruct y as [y py]; unfold nz_lt in *; simpl in *.
   omega.
   assert (y<S n\/y=S n). omega. destruct H0.
    assert (S n<>O); auto.
    assert (nz_lt (exist _ y py) (exist _ (S n) H1)). unfold nz_lt; simpl; assumption.
    fold nz_lt in *. apply Acc_inv with (exist (fun n0:nat=>n0<>O) (S n) H1). apply IHn.
    unfold nz_lt; simpl; assumption.
    rewrite <- H0 in IHn. apply IHn.
Defined.

Theorem nz_lt_wf: well_founded nz_lt. Proof. exact nz_Acc. Qed.

Lemma pred_wf: forall (n m:nz), nz_lt nz_one n -> m = nz_pred n -> nz_lt m n.
Proof.
 intros. unfold nz_lt, nz_pred in *. destruct n as [n pn], m as [m pm]. simpl in *.
 destruct n, m; try omega. simpl in *. inversion H0. omega. 
Defined.