Coq 递减参数(什么是程序固定点)

Coq 递减参数(什么是程序固定点),coq,termination,totality,Coq,Termination,Totality,考虑以下固定点: 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 wi

考虑以下固定点:

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拒绝以下固定点,因为它无法猜测递减的固定点(有时
列表的头部松动,有时是
列表)

这表明可以通过使用
程序固定点
并指定
{measure((左长)+(右长))}
来解决这个问题

我的问题是:

  • 常规
    固定点
    程序固定点
    之间有什么区别
  • 是否可以在常规的
    固定点中显式显示递减参数
  • 下一个义务是什么
      • Coq中的
        Fixpoint
        命令使用Coq的原语
        fix
        构造递归函数,该原语检查结构递归以确保终止。这是Coq中唯一的递归,所有其他技术最终都会使用某种形式的
        fix

        程序固定点
        是的一项功能,它允许使用稍微扩展的语言编写定义,然后将这些定义编译成Coq定义<代码>程序定点
        接受任何递归函数,生成适当的证明义务,表明函数终止(通过减少每个递归子调用上的参数的某些度量),然后将定义和终止证明打包到Coq定义中,该定义从结构上减少参数。如果这听起来很神奇的话,它基本上就是,但它很好地解释了如何进行这种编码

      • 是的,您可以添加一个
        {struct arg}
        注释来明确指定哪个参数在结构上减少:
        定点减少(哪个:我的类型)(左-右:列出我的类型){struct右}:列出我的类型
        。这对您的示例没有帮助,因为您的函数通常不会在结构上减少这两个参数。所有基本的
        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
        
      • 通过
        程序定点
        可以从
        下一个义务
        中获得两种类型的目标:第一,每个子调用都有一个较小的参数(使用
        度量
        ,“较小”是使用程序固定点
        不会自动为
        Nat.lt
        执行此操作,因为它应该知道相关的定理。请注意,
        Program
        具有比一般递归更多的功能,因此它还可以根据您编写的定义生成与这些功能相关的其他目标