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

如何在Coq中编写以下形式的函数?,coq,termination,totality,Coq,Termination,Totality,只有当函数的arg是传递的arg的直接子项,以便Coq可以看到它实际上终止时,才允许递归吗?如果函数g保留作为子项的属性,则可以编写这样的函数f 一些标准函数具有此属性,例如pred,sub: f x = f (g subtermOfX) 另一方面,一些(标准)函数没有此属性,但可以重写以弥补此缺陷。例如,标准的tl函数不保留subterm属性,因此以下操作失败: From Coq Require Import Arith List. Import ListNotations. Fixpoi

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

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

一些标准函数具有此属性,例如
pred
sub

f x = f (g subtermOfX)
另一方面,一些(标准)函数没有此属性,但可以重写以弥补此缺陷。例如,标准的
tl
函数不保留subterm属性,因此以下操作失败:

From 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.
但是如果我们像这样重新定义尾部函数

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.

tl
new\u tl
之间唯一的区别是,在空输入列表的情况下,
tl
返回
[]
,但
new\u tl
返回原始列表。

我认为这个问题实际上是两个问题。你能把它们分开吗?@AntonTrunov你能看看这个问题吗?
Fixpoint bar (xs : list nat) : list nat :=
  match xs with
  | [] => []
  | x :: xs' => bar (new_tl xs')
  end.