为什么';t Coq';s终止检查器支持一个参数在结构上变小而其他参数保持不变的情况
Coq的终止检查器不喜欢以下功能:为什么';t Coq';s终止检查器支持一个参数在结构上变小而其他参数保持不变的情况,coq,termination,Coq,Termination,Coq的终止检查器不喜欢以下功能: Fixpoint interleave (A : Type) (l1 l2 : list A) : list A := match l1 with | cons h1 t1 => cons h1 (interleave l2 t1) | nil => l2 end. 但是,其他一些具有类似终止检查器的语言(如Lean、Idris和Isabelle)接受此类函数。我想知道为什么Coq的终止检查器不会接受这样的函数,每次至少有一个参
Fixpoint interleave (A : Type) (l1 l2 : list A) : list A :=
match l1 with
| cons h1 t1 => cons h1 (interleave l2 t1)
| nil => l2
end.
但是,其他一些具有类似终止检查器的语言(如Lean、Idris和Isabelle)接受此类函数。我想知道为什么Coq的终止检查器不会接受这样的函数,每次至少有一个参数在结构上变小,而没有一个参数变大。在我看来,如果至少有一个参数总是在变小,而没有一个参数在增长,那么函数最终必须终止,或者是我遗漏了什么情况
编辑:似乎我在这里选择了一个糟糕的例子,因为显然伊德里斯和莱恩也无法处理它。一个更好的例子是中给出的固定中固定公式;我知道我成功地在精益和Idris中直接实现了相同的功能,而不需要在修复构造中进行修复。此外,最初的问题仍然存在:为什么不支持这种构造?正如gallais所建议的,您可以使用
度量值:
Require Import PeanoNat.
Require Import Coq.Program.Wf.
Program Fixpoint interleave (A : Type) (l1 l2 : list A) {measure (length l1 + length l2)} : list A :=
match l1 with
| nil => l2
| cons h1 t1 => cons h1 (interleave A l2 t1)
end.
Next Obligation.
simpl.
rewrite Nat.add_comm.
apply Nat.lt_succ_diag_r.
Defined.
Next Obligation.
Admitted.
在定义之后,你需要证明两件事:第一,在每一步,度量值都会减少;第二,这项措施是有根据的。完成两个证明后,您的定义就完成了。实际上,Coq终止检查器比您提到的语言中使用的版本早一代,所以它的功能不太强大。您可以使用Equations
插件获得更接近Coq中最先进的终止检查功能。Idris不接受此功能为total(我尝试过Idris v1.1.1)Lean(版本3.3.1,提交1b4d2a850afd)也不接受它等式
确实是函数
和程序
的继承者,并且已经得到Coq开发团队的正式支持。事实上,在某一点上,它将与Coq一起分发。如果所有其他方法都失败,您可以手动在参数对上定义适当的“小于”关系,证明它是有根据的(如果您需要评估函数,还可能确保证明是透明的定义),然后编写一个helper函数,它将一个Acc
证明作为一个额外参数设置为固定点的递减参数。