{-# OPTIONS --safe #-}

module Data.Nat.Properties where

open import Prelude
open import Agda.Builtin.Nat using (_+_; _-_) public

case-nat : (P :   Type p)
          P zero
          (∀ n  P (suc n))
           n  P n
case-nat P z s zero    = z
case-nat P z s (suc n) = s n

case-nat′ : A  (  A)    A
case-nat′ = case-nat _

is-zero :   Bool
is-zero = case-nat′ true (const false)

private variable n m : 

zero≢suc : zero  suc n
zero≢suc = true≢false  cong is-zero

suc≢zero : suc n  zero
suc≢zero = false≢true  cong is-zero

module DiscreteNat where
  _≡ᴮ_ :     Bool
  zero  ≡ᴮ zero  = true
  suc x ≡ᴮ suc y = x ≡ᴮ y
  _     ≡ᴮ _     = false

  sound : (x y : )  T (x ≡ᴮ y)  x  y
  sound zero    zero    p = refl
  sound (suc x) (suc y) p = cong suc (sound x y p)

  complete : (x : )  T (x ≡ᴮ x)
  complete zero    = _
  complete (suc x) = complete x

discreteNat : Discrete 
discreteNat = from-bool-eq record { DiscreteNat }

isSetNat : isSet 
isSetNat = Discrete→isSet discreteNat

suc-inj : suc n  suc m  n  m
suc-inj {n = n} = cong (case-nat′ n id)

+-suc :  n m  n + suc m  suc n + m
+-suc zero m = refl
+-suc (suc n) m = cong suc (+-suc n m)

+-zero :  n  n + zero  n
+-zero zero = refl
+-zero (suc n) = cong suc (+-zero n)

+-comm :  n m  n + m  m + n
+-comm zero m = sym (+-zero m)
+-comm (suc n) m = cong suc (+-comm n m) ; sym (+-suc m n)

data Ordering :     Type where
  less    :  m k  Ordering m (suc (m + k))
  equal   :  m    Ordering m m
  greater :  m k  Ordering (suc (m + k)) m

compare :  m n  Ordering m n
compare zero    zero    = equal   zero
compare (suc m) zero    = greater zero m
compare zero    (suc n) = less    zero n
compare (suc m) (suc n) with compare m n
... | less    m k = less (suc m) k
... | equal   m   = equal (suc m)
... | greater n k = greater (suc n) k

NonZero :   Type
NonZero zero    = 
NonZero (suc n) = 

open import Agda.Builtin.Nat using (mod-helper)

_mod_ : (n m : )   _ : NonZero m   
n mod suc m = mod-helper 0 m n m