如何在Coq中的两个参数上归纳定义一个函数?


14

我如何才能说服Coq以下给出的递归函数终止?该函数带有两个归纳参数。从直觉上讲,由于任何一个参数都已分解,因此递归终止。

具体来说,该函数将两棵树作为输入。

Inductive Tree :=
| Tip: Tree
| Bin: Tree -> Tree -> Tree.

在“树”上,我喜欢执行以下归纳样式。

Inductive TreePair :=
| TipTip : TreePair
| TipBin : Tree -> Tree -> TreePair
| BinTip : Tree -> Tree -> TreePair
| BinBin : TreePair -> TreePair -> TreePair.

Fixpoint pair (l r: Tree): TreePair :=
  match l with
    | Tip =>
      match r with
        | Tip => TipTip
        | Bin rl rr => TipBin rl rr
      end
    | Bin ll lr =>
      match r with
        | Tip => BinTip ll lr
        | Bin rl rr => BinBin (pair l rl) (pair lr r)
      end
  end.

接受TreePair的定义,但是函数对的定义会产生错误消息:

Error: Cannot guess decreasing argument of fix.

因此,我对如何说服Coq终止感兴趣。


1
您是否尝试过将l和r一起作为一种产品而不是使用currying?这应该可以帮助它。
Per Vognsen

1
有人认为这个问题与编程有关,超出了本网站的范围。虽然我不确定是否同意,但您可能想了解潜在的问题。如果有人对适当性有话要说,请写在我链接到的元讨论中。
伊藤刚(Tsuyoshi Ito)2010年

3
这个问题实际上是关于在数据结构上指定单调递减的界限,以确保操作pair定义良好。Coq仅仅是交通工具。
戴夫·克拉克2010年

Answers:


12

Coq的定点定义要求归纳调用接收结构上更小的参数。从深处看,一个固定点构造只接受一个参数:对于两个参数,没有内置的递归定义概念。幸运的是,Coq 对结构较小定义包括高阶类型,它的功能非常强大。

您的两个参数定点定义遵循一个简单的模式:第一个参数变小,或者第一个参数保持不变,第二个参数变小。可以通过简单的修复程序来处理这种相当常见的模式。

Fixpoint pair l := fix pair1 (r : Tree) :=
  match l with
    | Tip => match r with
              | Tip => TipTip
              | Bin rl rr => TipBin rl rr
            end
    | Bin ll lr => match r with
                    | Tip => BinTip ll lr
                    | Bin rl rr => BinBin (pair1 rl) (pair lr r)
                   end
  end.

对于更复杂的情况,或者如果您喜欢这种方式,则可以更接近于数学课程中所讲授的方式使用递归,通过逐步计算和单独的有根据的自变量(通常使用整数度量)构建固定点。您还可以使您的定义看起来更像是一种非全部语言的经典程序,并使用Program白话来单独终止。


现在我知道这就是我要的!
yhirai

如果我推fix pair1 r入顶层的第二个分支match(当然要使第一个分支相应地返回一个函数类型),会有所不同吗?

@plmday:双向均可。对于扩展性的某种合理定义,它们在扩展上是等效的,更重要的是,它们都具有良好的类型(扩展重写不会更改任何相关的协方差(正性)属性)。
吉尔(Gilles)“所以,别再邪恶了”,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.