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
的版本的想法相同