Recursion 归纳型与nat的相互递归

Recursion 归纳型与nat的相互递归,recursion,coq,termination,Recursion,Coq,Termination,考虑这个例子: Inductive T := | foo : T | bar : nat -> T -> T. Fixpoint evalT (t:T) {struct t} : nat := match t with | foo => 1 | bar n x => evalBar x n end with evalBar (x:T) (n:nat) {struct n} : nat := match n with | O => 0 |

考虑这个例子:

Inductive T :=
| foo : T
| bar : nat -> T -> T.

Fixpoint evalT (t:T) {struct t} : nat :=
  match t with
  | foo => 1
  | bar n x => evalBar x n
  end
with evalBar (x:T) (n:nat) {struct n} : nat :=
  match n with
  | O => 0
  | S n' => (evalT x) + (evalBar x n')
  end.
Coq拒绝了它,但有一个错误:对evalBar的递归调用的主参数等于“n”,而不是“x”


我知道终端检查器被两种不相关的感应类型(T和nat)弄糊涂了。然而,看起来我试图定义的函数确实会终止。我怎样才能让Coq接受它呢?

我找到的一个解决方案是使用
nat\u rec
而不是
evalBar

Fixpoint evalT (t:T) {struct t} : nat :=
  match t with
  | foo => 1
  | bar n x => @nat_rec _ 0 (fun n' t' => (evalT x) + t') n
  end.

它可以工作,但我希望我可以在
evalBar
定义下隐藏
nat\u rec
,以隐藏详细信息。在我的实际项目中,这种构造被使用了好几次。

另一种解决方案是使用嵌套的固定点

Fixpoint evalT (t:T) {struct t} : nat :=
  match t with
  | foo => 1
  | bar n x => let fix evalBar n {struct n} :=
                 match n with
                 | 0 => 0
                 | S n' => Nat.add (evalT x) (evalBar n')
                 end
               in evalBar n
  end.
重要的一点是从
evalBar
中删除参数
x
。因此,对
evalT
的递归调用是在
bar n x
x
上完成的,而不是作为
evalBar
参数给出的
x
,因此终止检查器可以验证
evalT
的定义

这与另一个答案中提出的具有
nat_rec
的版本的想法相同