Следующий код совершенно нормально в Haskell:Прекращение проверки вызова рекурсивной функции в Agda
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
.
Я пробовал использовать coinduction, настройка опции --termination-depth=4
- не помогает. Вставка {-# NO_TERMINATION_CHECK #-}
в блок mutual
помогает, но это похоже на обман.
Есть ли чистый способ сделать Agda компилировать код? Есть ли ограничения на определение термина «Агда»?
Я еще не слишком хорошо знаком с corecursion, поэтому я не прокомментировал, может ли он быть использован в ваших интересах здесь. –
Я согласен с тобой. Но с другой точки зрения результат 'dh' - это просто пара' ℕ ', а оценка' a' и 'b' может быть разложена:' aQ = 2^ad; bQ = 2^bd; abQ = bQ^ad; baQ = aQ^bd'. В «ключевом слове» нет необходимости. Весь смысл 'dh' заключается в том, чтобы инкапсулировать шаги алгоритма и абстрагировать порядок оценки. В разложенной форме код становится слишком многословным. –