我想划分两个自然数。我已经做了这样的功能
_/_ : N -> N -> frac
m / one = m / one
(suc m) / n = ?? I dont know what to write here.
请帮忙。
答案 0 :(得分:6)
正如@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
然后使用我描述的内容here,您可以重复从另一个数字中减去一个数字,直到差异小于第二个数字:
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
模块中的版本类似的版本(仅限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
整个code。
答案 1 :(得分:2)
除法通常被定义为迭代减法,这需要略微不寻常的归纳原理。参见例如the definition in the standard library