Recursion 协助Agda&x27;s终止检查器来生成递归函数

Recursion 协助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

假设我们希望为某些类型定义一个函数₀ ⋯ 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 → 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