协助Agda的终止检查器进行递归功能

时间:2014-04-28 13:43:58

标签: recursion termination agda

假设我们希望为某些类型定义一个函数A 0 ...Aₙ和B

f : A₀ ⋯ Aₙ → B
f x₀ ⋯ xₙ = ... recursive call to f ...

假设此定义在结构上不是递归的。

我还假设我有以下定义:

  1. 一个函数g : A₀ ⋯ Aₙ → ℕ,它占用了一些子集 f对自然数的论证;

  2. 针对f的每个案例: 证明g传递给递归的参数 call严格小于传入参数的g (使用自然数字的内置_< _或_<'_关系)。

  3. 我如何将这些部分组合在一起以形成递归函数, 使用Agda“标准”库中的Induction模块?


    这个问题是关于同一主题的this question的后续问题,已经给出了非常完整的答案。但是,我觉得示例函数的类型很遗憾地被选为ℕ → ℕ,这使我很难看到它如何扩展到一般情况。

    另外,请注意,我并没有期待一个大的答案,解释有充分理由的归纳及其在Agda中的实施背后的运作,正如@Vitus所提供的那样quite an elaborate answer for this

1 个答案:

答案 0 :(得分:2)

如果你有一个函数A → B而且你知道B有一个有充分根据的关系,你可以在A上建立一个有充分根据的关系:

_<_ : B → B → Set
f   : A → B

_≺_ : A → A → Set
x ≺ y = f x < f y
-- or more concisely
_≺_ = _<_ on f -- 'on' come from Function module

证明_≺_也是有充分根据的并不是那么难,但它已经在标准库中,所以我们只会使用它:

open Inverse-image
  {A = A}     -- new type
  {_<_ = _≺_} -- new relation
  f
  renaming (well-founded to <⇒≺-well-founded)

Inverse-image导出well-founded值作为证明。然后我们可以使用这个值来获取为我们递归的实际函数:

≺-well-founded = <⇒≺-well-founded <-well-founded

open All (≺-well-founded)
  renaming (wfRec to ≺-rec)

就是这样,≺-rec现在可用于实现以A作为参数类型的递归函数。


≺-rec大致用作:

g : A → C
g = ≺-rec
  _  {- level paremeter -}
  _  {- A → Set; return type in case Agda cannot figure out the dependency -}
  go {- helper function -}
  where
  go : ∀ x → (∀ y → y ≺ x → C) → C
  go x rec = ... (rec arg proof) ...

arg是递归出现的参数,proof证明了参数实际上更小。

当返回类型取决于参数时,辅助函数看起来大致如下:

go : ∀ x → (∀ y → y ≺ x → C y) → C x

当处理具有多个参数的函数时,您需要将它们组合成一个类型,以便关系可以讨论所有这些。这通常意味着成对,或者如果参数之间存在依赖关系,则表示依赖对。