考虑以下修复点:
Require Import Coq.Lists.List.
Import ListNotations.
Inductive my_type: Type:=
| Left: my_type
| Right: my_type
.
Fixpoint decrease (which: my_type) (left right: list my_type) : list my_type :=
match which with
| Left =>
match left with
| [] => []
| a::tl => decrease a tl right
end
| Right =>
match right with
| [] => []
| a::tl => decrease a left tl
end
end.
Coq拒绝以下修复点,因为它无法猜测减少的修复点(有时left
列表会失去它的头部,有时它是right
列表。
此answer表示可以使用Program Fixpoint
并指定{measure ((length left)+(length right))}
来解决此问题。
我的问题是:
Fixpoint
和Program Fixpoint
之间有什么区别?Fixpoint
中明确减少参数?Next Obligation
目标是什么?答案 0 :(得分:5)
Coq中的Fixpoint
命令使用Coq的原语fix
构造递归函数,该函数检查结构递归以确保终止。这是Coq中唯一的递归,所有其他技术最终都是某种fix
。
Program Fixpoint
是Program的一个特性,它允许以稍微扩展的语言编写定义,然后将其编译为Coq定义。 Program Fixpoint
接受任何递归函数,生成一个适当的证明义务,显示函数终止(通过减少每个递归子查询的一些参数),然后将定义和终止证明打包成一个结构上减少的Coq定义一个论点。如果这听起来很神奇,那么CPDT可以很好地解释如何进行这种编码。
是的,您可以添加{struct arg}
注释以明确指定哪个参数在结构上正在减少:Fixpoint decrease (which: my_type) (left right: list my_type) {struct right} : list my_type
。这对你的例子没有帮助,因为你的函数通常不会在结构上减少任何一个参数。所有原始fix
构造都有struct
注释,但Coq通常可以在您编写Fixpoint
时自动推断它。例如,这里是Nat.add
:
Nat.add =
fix add (n m : nat) {struct n} : nat :=
match n with
| 0 => m
| S p => S (add p m)
end : nat -> nat -> nat
从Next Obligation
Program Fixpoint
获得两种类型的目标:首先,每个子查询的参数较小(使用measure
,"较小的"是使用< on nats定义,第二,"较小"关系是有根据的;也就是说,它没有无限下降的越来越小的对象序列。我不确定Program Fixpoint
为什么Nat.lt
不会自动为Program
执行此操作,因为它应该知道相关定理。请注意,PUB/SUB
具有的功能不仅仅是更一般的递归,因此它可以生成与这些功能相关的其他目标,具体取决于您编写的定义。