以下Haskell代码是完全没有问题的:
dh :: Int -> Int -> (Int, Int)
dh d q = (2^d, q^d)
a = dh 2 (fst b)
b = dh 3 (fst a)
在Agda中类似的代码无法编译(终止检查失败):
infixl 9 _^_
_^_ : ℕ → ℕ → ℕ
x ^ zero = 1
x ^ suc n = x * (x ^ n)
dh : ℕ -> ℕ -> ℕ × ℕ
dh d q = 2 ^ d , q ^ d
mutual
a = dh 2 (proj₁ b)
b = dh 3 (proj₁ a)
变量 a
的定义中使用了结构大小相同的 a
,因此出现了循环。似乎终止检查器不会查看 dh
的定义。
我尝试使用协同归纳,设置选项 --termination-depth=4
—— 没有帮助。
在 mutual
块内插入 {-# NO_TERMINATION_CHECK #-}
可以解决问题,但这看起来像是作弊。
有没有一种干净的方法让 Agda 编译代码?Agda 的终止检查器是否有一些根本性的限制?
dh
的结果只是一对ℕ
,而且a
和b
的计算可以分解为:aQ = 2 ^ ad ; bQ = 2 ^ bd ; abQ = bQ ^ ad ; baQ = aQ ^ bd
。甚至不需要使用mutual
关键字。dh
的整个重点在于封装算法步骤并抽象出评估顺序。以分解形式呈现的代码过于冗长。 - Vlad Semenov