Recursion Prop中的Bove Capretta谓词

Recursion Prop中的Bove Capretta谓词,recursion,agda,dependent-type,Recursion,Agda,Dependent Type,Bove Capretta方法()是一个巧妙的技巧,用于在Agda等语言中对非结构化递归或部分函数进行建模。函数的终止输入以归纳谓词为特征,函数被重写为将谓词作为参数 例如,假设我们想在Agda中编写以下以2为底的对数定义(使用moduleData.Nat): 遗憾的是,此定义未通过终止检查器。根据上述Capretta,可以定义以下谓词: data Loggable : ℕ → Set where log-n≡0 : Loggable 0 log-n≡1 : Loggable 1

Bove Capretta方法()是一个巧妙的技巧,用于在Agda等语言中对非结构化递归或部分函数进行建模。函数的终止输入以归纳谓词为特征,函数被重写为将谓词作为参数

例如,假设我们想在Agda中编写以下以2为底的对数定义(使用module
Data.Nat
):

遗憾的是,此定义未通过终止检查器。根据上述Capretta,可以定义以下谓词:

data Loggable : ℕ → Set where
    log-n≡0 : Loggable 0
    log-n≡1 : Loggable 1
    log-n≡n : ∀ {n} → Loggable ⌊ n /2⌋ → Loggable n
然后扩展原始定义,将
Loggable
作为额外参数:

log2 : (n : ℕ) → Loggable n → ℕ
log2 0 _ = 0
log2 1 _ = 1
log2 n (log-n≡n p) = suc (log2 ⌊ n /2⌋ p)
由于
Loggable
谓词用作结构上递减的参数,因此它现在成功地通过了终止检查器。这一切都按预期进行

现在,由于谓词仅用于说服终止检查器,因此将其移动到sort
Prop
是有意义的,因为它不应该有任何计算效果。事实上,检查我们对
log2
的新定义也表明了这一点,因为谓词不用于进行任何尚未由另一个参数确定的大小写拆分

这就是问题所在。首先,将
Loggable
设置为
Prop
禁止在排序
Set
时在其上拆分大小写,这是我们新的
log2
函数中的情况。通常的解决方案是引入一个在sort
Prop
中操作的辅助“反转引理”,它破坏谓词并提取我们需要的部分。不幸的是,这引入了一个新问题——
log2
的结构终止将被破坏,因为Agda无法看到调用“反转引理”的结果在结构上小于其输入


(请注意,这个问题的等价物可以用Coq编写,它不会遇到相同的问题,因为它在检查终止之前规范化了表达式,因此提出的“反转引理”方法成功了。)

与Coq中的
Prop
不同(但与
sProp
类似),Agda的
Prop
universe支持定义证明无关性。这意味着
Prop
中类型的任意两个元素定义上等于转换检查器。另一方面,这也意味着对一个术语的求值永远不会停留在
Prop
中类型的参数上,因此这些参数不能用于证明终止。因此,不幸的是,这意味着上述Capretta方法不能与Agda的
Prop
universe一起使用。

log2 : (n : ℕ) → Loggable n → ℕ
log2 0 _ = 0
log2 1 _ = 1
log2 n (log-n≡n p) = suc (log2 ⌊ n /2⌋ p)