簡體   English   中英

如何在Agda中定義除法運算符?

[英]How to define division operator in Agda?

我想分兩個自然數。 我做了這樣的功能

_/_ : N -> N -> frac
m / one = m / one
(suc m) / n = ??        I dont know what to write here.

請幫忙。

正如@gallais所說,你可以明確地使用有根據的遞歸,但我不喜歡這種方法,因為它完全不可讀。

此數據類型

record Is {α} {A : Set α} (x : A) : Set α where
  ¡ = x
open Is

! : ∀ {α} {A : Set α} -> (x : A) -> Is x
! _ = _

允許將值提升到類型級別,例如,您可以定義類型安全的pred函數:

pred⁺ : ∀ {n} -> Is (suc n) -> ℕ
pred⁺ = pred ∘ ¡

然后

test-1 : pred⁺ (! 1) ≡ 0
test-1 = refl

typechecks,而

fail : pred⁺ (! 0) ≡ 0
fail = refl

沒有。 可以用相同的方式定義具有正減數的減法(以確保良好的基礎):

_-⁺_ : ∀ {m} -> ℕ -> Is (suc m) -> ℕ
n -⁺ im = n ∸ ¡ im

然后使用我在這里描述的東西,你可以重復從另一個數字中減去一個數字,直到差異小於第二個數字:

lem : ∀ {n m} {im : Is (suc m)} -> m < n -> n -⁺ im <′ n
lem {suc n} {m} (s≤s _) = s≤′s (≤⇒≤′ (n∸m≤n m n))

iter-sub : ∀ {m} -> ℕ -> Is (suc m) -> List ℕ
iter-sub n im = calls (λ n -> n -⁺ im) <-well-founded lem (_≤?_ (¡ im)) n

例如

test-1 : iter-sub 10 (! 3) ≡ 10 ∷ 7 ∷ 4 ∷ []
test-1 = refl

test-2 : iter-sub 16 (! 4) ≡ 16 ∷ 12 ∷ 8 ∷ 4 ∷ []
test-2 = refl

div⁺然后很簡單

_div⁺_ : ∀ {m} -> ℕ -> Is (suc m) -> ℕ
n div⁺ im = length (iter-sub n im)

和一個類似於Data.Nat.DivMod模塊中的Data.Nat.DivMod (只有沒有Mod部分):

_div_ : ℕ -> (m : ℕ) {_ : False (m ≟ 0)} -> ℕ
n div  0      = λ{()}
n div (suc m) = n div⁺ (! (suc m))

一些測試:

test-3 : map (λ n -> n div 3)
           (0 ∷ 1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ 6 ∷ 7 ∷ 8 ∷ 9 ∷ [])
         ≡ (0 ∷ 0 ∷ 0 ∷ 1 ∷ 1 ∷ 1 ∷ 2 ∷ 2 ∷ 2 ∷ 3 ∷ [])
test-3 = refl

但請注意,標准庫中的版本還包含完整性:

property  : dividend ≡ toℕ remainder + quotient * divisor

整個代碼

除法通常被定義為迭代減法,這需要略微不尋常的歸納原理。 參見例如標准庫中的定義

暫無
暫無

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

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