簡體   English   中英

帶有模糊終止的條款

[英]With clauses obscuring termination

我正在嘗試在 agda 中定義二進制數,但 agda 看不到⟦_⇑⟧正在終止。 我真的不想打破可訪問性關系。 如何向 agda 顯示 n 變小?

module Binary where

open import Data.Nat using (ℕ; _+_; +-suc)
open ℕ

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 ⇓⟧

⟦_⇑⟧ : ℕ → 𝔹
⟦ zero ⇑⟧ = 𝕫
⟦ suc n ⇑⟧ with parity n
⟦ suc .(k + k) ⇑⟧ | 𝕖 k = 𝕠 ⟦ k ⇑⟧
⟦ suc .(suc (k + k)) ⇑⟧ | 𝕠 k = 𝕖 ⟦ k ⇑⟧

錯誤:

Termination checking failed for the following functions:
  ⟦_⇑⟧
Problematic calls:
  ⟦ k ⇑⟧

終止檢查失敗的原因很充分,因為以下 function 在其輸入上沒有結構遞歸:

 ⟦_⇑⟧: ℕ → ⟦ zero ⇑⟧ = ⟦ suc n ⇑⟧ with parity n ⟦ suc.(k + k) ⇑⟧ | k = ⟦ k ⇑⟧ ⟦ suc.(suc (k + k)) ⇑⟧ | k = ⟦ k ⇑⟧

Agda 甚至會告訴你有問題的調用是什么: ⟦ k ⇑⟧ (在這種情況下,有兩個格式不正確的調用)。

雖然我同意它可能看起來function 是在結構上更小的參數上調用的,但事實並非如此。 要了解原因,您必須看到k用作 function 調用_+_的輸入,並且只有此 function 的結果在結構上小於n ,而不是k本身。 而且 agda 無法知道關於_+_的以下屬性:

∀ {n} → n < suc (n + n)

如果您提供此類引理的證明,您可以使用_<_有充分根據的事實來使您的 function 在結構上遞歸Acc ,但您似乎不願意這樣做。

理解為什么 Agda不能知道這會終止的一個簡單方法如下:假設您將suc.(k + k)替換suc.(a ∸ b)並在a上遞歸調用 function 。 從 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 在評估test時返回2

考慮定義:

test₁ : ℕ
test₁ = ⟦ ⟦ 16 ⇑⟧ ⇓⟧

Agda 在評估test₁時返回14

為了更正您的定義,您可以從標准庫中所做的工作中汲取靈感,無論是在模塊 Data.Bin(已棄用)中還是在模塊 Data.Nat.Binary 中,具體取決於您擁有的 stdlib 版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM