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的终止检查器不会接受这样的函数,其中每次至少有一个参数在结构上变小,并且没有任何参数变大。在我看来,如果至少有一个论点总是变得越来越小,而且没有一个论证在增长,那么这个函数最终必须终止,或者是否有一些我失踪的情况?
编辑:似乎我在这里选择了一个可怕的例子,因为显然伊德里斯和精益也无法处理它。一个更好的例子是How to deal with really large terms generated by Program Fixpoint in Coq?中给出的固定修复公式;我知道我设法在Lean和Idris中直接实现了相同的功能,而不需要修复修复。此外,最初的问题仍然存在:为什么不支持这种结构?
答案 0 :(得分:1)
就像加莱建议的那样,您可以使用measure
:
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.
定义之后,您需要证明两件事:首先,在每个步骤中,度量都减小;其次,该措施是有充分根据的。完成两个证明后,您的定义就完成了。