假设我们希望为某些类型定义一个函数A 0 ...Aₙ和B
f : A₀ ⋯ Aₙ → B
f x₀ ⋯ xₙ = ... recursive call to f ...
假设此定义在结构上不是递归的。
我还假设我有以下定义:
一个函数g : A₀ ⋯ Aₙ → ℕ
,它占用了一些子集
f
对自然数的论证;
针对f
的每个案例:
证明g
传递给递归的参数
call严格小于传入参数的g
(使用自然数字的内置_< _或_<'_关系)。
我如何将这些部分组合在一起以形成递归函数,
使用Agda“标准”库中的Induction
模块?
这个问题是关于同一主题的this question的后续问题,已经给出了非常完整的答案。但是,我觉得示例函数的类型很遗憾地被选为ℕ → ℕ
,这使我很难看到它如何扩展到一般情况。
另外,请注意,我并没有期待一个大的答案,解释有充分理由的归纳及其在Agda中的实施背后的运作,正如@Vitus所提供的那样quite an elaborate answer for this。
答案 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
当处理具有多个参数的函数时,您需要将它们组合成一个类型,以便关系可以讨论所有这些。这通常意味着成对,或者如果参数之间存在依赖关系,则表示依赖对。