Recursion 协助Agda&x27;s终止检查器来生成递归函数
假设我们希望为某些类型定义一个函数₀ ⋯ A.ₙ BRecursion 协助Agda&x27;s终止检查器来生成递归函数,recursion,termination,agda,Recursion,Termination,Agda,假设我们希望为某些类型定义一个函数₀ ⋯ A.ₙ B f : A₀ ⋯ Aₙ → B f x₀ ⋯ xₙ = ... recursive call to f ... 假设此定义在结构上不是递归的 还假设我对以下内容有定义: a函数g:a₀ ⋯ A.ₙ → ℕ,它接受 f的参数是一个自然数 对于f的每种情况: 一种证明g传递给递归 调用严格小于传入参数的g (如果有函数a,则使用内置的→ B并且您知道B具有良好的基础关系,您可以在a上构建良好的基础关系: _<_ : B → B → Set
f : A₀ ⋯ Aₙ → B
f x₀ ⋯ xₙ = ... recursive call to f ...
假设此定义在结构上不是递归的
还假设我对以下内容有定义:
g:a₀ ⋯ A.ₙ → ℕ代码>,它接受
f
的参数是一个自然数
f
的每种情况:
一种证明g
传递给递归
调用严格小于传入参数的g
(如果有函数
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
逆图像
导出有充分根据的
值作为证明。然后,我们可以使用该值来获得为我们执行递归的实际函数:
≺-well-founded = <⇒≺-well-founded <-well-founded
open All (≺-well-founded)
renaming (wfRec to ≺-rec)
arg
是递归发生的参数,proof
是该参数实际上更小的证明
当返回类型取决于参数时,helper函数大致如下所示:
go : ∀ x → (∀ y → y ≺ x → C y) → C x
当处理具有多个参数的函数时,您需要将这些参数组合成一种类型,以便关系可以讨论所有参数。这通常意味着成对,或者,如果参数之间存在依赖关系,则是依赖对。对您有效吗?如果有效,我将写一个答案。@Vitus:如果B de取决于₀ ⋯ A.ₙ? 我目前的尝试是使用来自
Arg
数据类型的几个笨拙的投影函数。@Vitus:为了了解更多的背景,我正在实现一个小型术语演算,f
是传递性,因此它的类型类似于(a B C:type)→ 术语A和术语B→ 术语B C→ 术语A C
。度量值g
是三种类型A
、B
和C
的函数。我更新了要点。解决方案大致相同;未修剪B
主要是为了方便。@Vitus:谢谢!这很有效。我翻译非依赖版本时遇到的问题是我编写∀ Y→ Y◃ x→ Bᶜ x
而不是∀ Y→ Y◃ x→ Bᶜ y
。
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) ...
go : ∀ x → (∀ y → y ≺ x → C y) → C x