Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
940 views
in Technique[技术] by (71.8m points)

functional programming - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As @gallais says you can use well-founded recursion explicitly, but I don't like this approach, because it's totally unreadable.

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? : ? {n} -> Is (suc n) -> ?
pred? = pred ° ?

Then

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

typechecks, while

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?_ : ? {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):

_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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...