Проверка завершения не выполняется по уважительным причинам, поскольку следующая функция не является структурно рекурсивной при вводе:
⟦_⇑⟧ : ℕ → ????
⟦ zero ⇑⟧ = ????
⟦ suc n ⇑⟧ with parity n
⟦ suc .(k + k) ⇑⟧ | ???? k = ???? ⟦ k ⇑⟧
⟦ suc .(suc (k + k)) ⇑⟧ | ???? k = ???? ⟦ k ⇑⟧
Agda даже сообщает вам, в чем проблема: ⟦ k ⇑⟧
. (в данном случае таких некорректных вызовов два).
Хотя я согласен, может выглядеть, что функция вызывается для аргумента структурно меньшего размера, но это не так. Чтобы понять почему, вы должны увидеть, что k
используется в качестве входных данных для вызова функции _+_
, и что только результат этой функции структурно меньше n
, а не сам k
. И у agda нет возможности узнать следующее свойство о _+_
:
∀ {n} → n < suc (n + n)
Если вы предоставите доказательство такой леммы, вы можете использовать тот факт, что _<_
хорошо обоснован, чтобы сделать вашу функцию структурно рекурсивной по сравнению с Acc
, но, похоже, вы не хотите этого делать.
Простой способ понять, почему Agda не может узнать об этом, заключается в следующем: представьте, что вы заменяете suc .(k + k)
на suc .(a ∸ b)
и рекурсивно вызываете свою функцию поверх a
. С точки зрения agda, оба случая являются одними и теми же, и в этом случае он обычно не завершается, если b
не совпадает с 0
.
Вот модуль, исправленный в части прекращения действия:
module Binary where
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
open import Data.Product
open import Induction.Nat
open import Induction.WellFounded
2* : ℕ → ℕ
2* n = n + n
data Parity : ℕ → Set where
???? : ∀ k → Parity (2* k)
???? : ∀ k → Parity (1 + 2* k)
parity : ∀ n → Parity n
parity zero = ???? 0
parity (suc n) with parity n
parity (suc .(k + k)) | ???? k = ???? k
parity (suc .(suc (k + k))) | ???? k rewrite sym (+-suc k k) = ???? (suc k)
data ???? : Set where
???? : ????
???? : ???? → ????
???? : ???? → ????
⟦_⇓⟧ : ???? → ℕ
⟦ ???? ⇓⟧ = 0
⟦ ???? b ⇓⟧ = 2* ⟦ b ⇓⟧
⟦ ???? b ⇓⟧ = 1 + 2* ⟦ b ⇓⟧
decr : ∀ {n} → n < suc (n + n)
decr {n} = s≤s (m≤m+n n n)
helper : (n : ℕ) → Acc _<_ n → ????
helper zero a = ????
helper (suc n) a with parity n
helper (suc .(k + k)) (acc rs) | ???? k = ???? (helper k (rs _ decr))
helper (suc .(suc (k + k))) (acc rs) | ???? k = ???? (helper k (rs _ (s≤s (<⇒≤ decr))))
⟦_⇑⟧ : ℕ → ????
⟦ n ⇑⟧ = helper n (<-wellFounded n)
Я тоже скептически относился к правильности ваших определений и оказался прав, например, учитывая следующее определение:
test : ℕ
test = ⟦ ⟦ 124 ⇑⟧ ⇓⟧
Agda возвращает 2
при оценке test
.
Учитывая определение:
test₁ : ℕ
test₁ = ⟦ ⟦ 16 ⇑⟧ ⇓⟧
Agda возвращает 14
при оценке test₁
Чтобы исправить свои определения, вы можете вдохновиться тем, что сделано в стандартной библиотеке, либо в модуле Data.Bin (не рекомендуется), либо в модуле Data.Nat.Binary, в зависимости от того, какая версия stdlib у вас установлена.
person
MrO
schedule
13.11.2019