简体   繁体   English

如何在Agda中定义除法运算符?

[英]How to define division operator in Agda?

I want to divide two natural number. 我想分两个自然数。 I have made function like this 我做了这样的功能

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

Please help. 请帮忙。

As @gallais says you can use well-founded recursion explicitly, but I don't like this approach, because it's totally unreadable. 正如@gallais所说,你可以明确地使用有根据的递归,但我不喜欢这种方法,因为它完全不可读。

This datatype 此数据类型

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

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

allows to lift values to the type level, for example you can define a type-safe pred function: 允许将值提升到类型级别,例如,您可以定义类型安全的pred函数:

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

Then 然后

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

typechecks, while typechecks,而

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

doesn't. 没有。 It's possible to define subtraction with positive subtrahend (to ensure well-foundness) in the same way: 可以用相同的方式定义具有正减数的减法(以确保良好的基础):

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

Then using stuff that I described here , you can repeatedly subtract one number from another until the difference is smaller than the second number: 然后使用我在这里描述的东西,你可以重复从另一个数字中减去一个数字,直到差异小于第二个数字:

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

For example 例如

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⁺ then is simply div⁺然后很简单

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

And a version similar to the one in the Data.Nat.DivMod module (only without the Mod part): 和一个类似于Data.Nat.DivMod模块中的Data.Nat.DivMod (只有没有Mod部分):

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

Some tests: 一些测试:

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

Note however, that the version in the standard library also contains the soundness proof: 但请注意,标准库中的版本还包含完整性:

property  : dividend ≡ toℕ remainder + quotient * divisor

The whole code . 整个代码

Division is usually defined as iterated substraction which requires a slightly unusual induction principle. 除法通常被定义为迭代减法,这需要略微不寻常的归纳原理。 See eg the definition in the standard library . 参见例如标准库中的定义

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM