3
f x = f (g subtermOfX)

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

4

1 回答 1

3

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

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

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.

另一方面,一些(标准)函数没有这个属性,但是可以重写来弥补这个缺陷。例如,标准tl函数不保留 subterm 属性,因此以下失败:

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_tl是在空输入列表的情况下tl返回[],但new_tl返回原始列表。

于 2017-12-23T09:41:51.450 回答