如何在Coq中编写以下形式的函数?

时间:2017-12-22 21:51:28

标签: coq termination totality

Packages

只有当函数的arg是传递的arg的直接子项时才允许递归,以便Coq可以看到它实际终止了吗?

1 个答案:

答案 0 :(得分:3)

如果函数g保留了作为子项的属性,则可以编写这样的函数pred

某些标准函数具有此属性,例如subFrom Coq Require Import Arith List. Import ListNotations. Fixpoint foo (x : nat) : nat := match x with | O => 42 | S x' => foo (pred x'). (* foo (x' - 1) works too *) end.

tl

另一方面,某些(标准)函数没有此属性,但可以重写以弥补此缺陷。例如。标准Fail Fixpoint bar (xs : list nat) : list nat := match xs with | [] => [] | x :: xs' => bar (tl xs') end. 函数不保留子项属性,因此以下操作失败:

Fixpoint new_tl {A : Type} (xs : list A) :=
  match xs with
  | [] => xs           (* `tl` returns `[]` here *) 
  | _ :: xs' => xs'
  end.

但如果我们重新定义尾部函数,那么

Fixpoint bar (xs : list nat) : list nat :=
  match xs with
  | [] => []
  | x :: xs' => bar (new_tl xs')
  end.

我们可以恢复所需的属性:

tl

new_tltl之间的唯一区别是,在空输入列表[]的情况下,返回new_tl,但public IEnumerable<Item> PickItems(Tab tab) { tab.Pick(); return tab.Items; } 会返回原始列表。