为什么Coq的终止检查器不支持一个参数结构较小而其他参数保持不变的情况

时间:2017-12-17 14:24:38

标签: 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的终止检查器不会接受这样的函数,其中每次至少有一个参数在结构上变小,并且没有任何参数变大。在我看来,如果至少有一个论点总是变得越来越小,而且没有一个论证在增长,那么这个函数最终必须终止,或者是否有一些我失踪的情况?

编辑:似乎我在这里选择了一个可怕的例子,因为显然伊德里斯和精益也无法处理它。一个更好的例子是How to deal with really large terms generated by Program Fixpoint in Coq?中给出的固定修复公式;我知道我设法在Lean和Idris中直接实现了相同的功能,而不需要修复修复。此外,最初的问题仍然存在:为什么不支持这种结构?

1 个答案:

答案 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.

定义之后,您需要证明两件事:首先,在每个步骤中,度量都减小;其次,该措施是有充分根据的。完成两个证明后,您的定义就完成了。