{-# OPTIONS --warning=error --safe #-} open import LogicalFormulae open import Agda.Primitive using (Level; lzero; lsuc; _⊔_) open import WellFoundedInduction open import Functions open import Orders module Naturals where data ℕ : Set where zero : ℕ succ : ℕ → ℕ {-# BUILTIN NATURAL ℕ #-} transitivityN = transitivity {_} {ℕ} infix 15 _+N_ infix 100 succ _+N_ : ℕ → ℕ → ℕ zero +N y = y succ x +N y = succ (x +N y) infix 25 _*N_ _*N_ : ℕ → ℕ → ℕ zero *N y = zero (succ x) *N y = y +N (x *N y) data _even : ℕ → Set where zero_is_even : zero even add_two_stays_even : ∀ x → x even → succ (succ x) even four_is_even : succ (succ (succ (succ zero))) even four_is_even = add_two_stays_even (succ (succ zero)) (add_two_stays_even zero zero_is_even) infix 5 _ n +N c) pr addingPreservesEqualityLeft : {a b : ℕ} (c : ℕ) → (a ≡ b) → (c +N a ≡ c +N b) addingPreservesEqualityLeft {a} {b} c pr = applyEquality (λ n -> c +N n) pr additionNIsAssociative : (a b c : ℕ) → ((a +N b) +N c) ≡ (a +N (b +N c)) additionNIsAssociative zero b c = refl additionNIsAssociative (succ a) zero c = transitivity (transitivity (applyEquality (λ n → n +N c) (applyEquality succ (addZeroRight a))) refl) (transitivity refl refl) additionNIsAssociative (succ a) (succ b) c = transitivity refl (transitivity refl (transitivity (applyEquality succ (additionNIsAssociative a (succ b) c)) refl)) productZeroIsZeroLeft : (a : ℕ) → (zero *N a ≡ zero) productZeroIsZeroLeft a = refl productZeroIsZeroRight : (a : ℕ) → (a *N zero ≡ zero) productZeroIsZeroRight zero = refl productZeroIsZeroRight (succ a) = productZeroIsZeroRight a productWithOneLeft : (a : ℕ) → ((succ zero) *N a) ≡ a productWithOneLeft a = transitivity refl (transitivity (applyEquality (λ { m -> a +N m }) refl) (additionNIsCommutative a zero)) productWithOneRight : (a : ℕ) → a *N succ zero ≡ a productWithOneRight zero = refl productWithOneRight (succ a) = transitivity refl (addingPreservesEqualityLeft (succ zero) (productWithOneRight a)) productDistributes : (a b c : ℕ) → (a *N (b +N c)) ≡ a *N b +N a *N c productDistributes zero b c = refl productDistributes (succ a) b c = transitivity refl (transitivity (addingPreservesEqualityLeft (b +N c) (productDistributes a b c)) (transitivity (equalityCommutative (additionNIsAssociative (b +N c) (a *N b) (a *N c))) (transitivity (addingPreservesEqualityRight (a *N c) (additionNIsCommutative (b +N c) (a *N b))) (transitivity (addingPreservesEqualityRight (a *N c) (equalityCommutative (additionNIsAssociative (a *N b) b c))) (transitivity (addingPreservesEqualityRight (a *N c) (addingPreservesEqualityRight c (additionNIsCommutative (a *N b) b))) (transitivity (addingPreservesEqualityRight (a *N c) (addingPreservesEqualityRight {b +N a *N b} {(succ a) *N b} c (refl))) (transitivity (additionNIsAssociative ((succ a) *N b) c (a *N c)) (transitivity (addingPreservesEqualityLeft (succ a *N b) refl) refl) ) )))))) succIsAddOne : (a : ℕ) → succ a ≡ a +N succ zero succIsAddOne a = equalityCommutative (transitivity (additionNIsCommutative a (succ zero)) refl) productPreservesEqualityLeft : (a : ℕ) → {b c : ℕ} → b ≡ c → a *N b ≡ a *N c productPreservesEqualityLeft a {b} {.b} refl = refl aSucB : (a b : ℕ) → a *N succ b ≡ a *N b +N a aSucB a b = transitivity {_} {ℕ} {a *N succ b} {a *N (b +N succ zero)} (productPreservesEqualityLeft a (succIsAddOne b)) (transitivity {_} {ℕ} {a *N (b +N succ zero)} {a *N b +N a *N succ zero} (productDistributes a b (succ zero)) (addingPreservesEqualityLeft (a *N b) (productWithOneRight a))) aSucBRight : (a b : ℕ) → (succ a) *N b ≡ a *N b +N b aSucBRight a b = additionNIsCommutative b (a *N b) multiplicationNIsCommutative : (a b : ℕ) → (a *N b) ≡ (b *N a) multiplicationNIsCommutative zero b = transitivity (productZeroIsZeroLeft b) (equalityCommutative (productZeroIsZeroRight b)) multiplicationNIsCommutative (succ a) zero = multiplicationNIsCommutative a zero multiplicationNIsCommutative (succ a) (succ b) = transitivityN refl (transitivityN (addingPreservesEqualityLeft (succ b) (aSucB a b)) (transitivityN {succ b +N (a *N b +N a)} {(a *N b +N a) +N succ b} (additionNIsCommutative (succ b) (a *N b +N a)) (transitivityN {(a *N b +N a) +N succ b} {a *N b +N (a +N succ b)} (additionNIsAssociative (a *N b) a (succ b)) (transitivityN {a *N b +N (a +N succ b)} {a *N b +N ((succ a) +N b)} (addingPreservesEqualityLeft (a *N b) (succCanMove a b)) (transitivityN {a *N b +N ((succ a) +N b)} {a *N b +N (b +N succ a)} (addingPreservesEqualityLeft (a *N b) (additionNIsCommutative (succ a) b)) (transitivityN {a *N b +N (b +N succ a)} {(a *N b +N b) +N succ a} (equalityCommutative (additionNIsAssociative (a *N b) b (succ a))) (transitivity (addingPreservesEqualityRight (succ a) (equalityCommutative (aSucBRight a b))) (transitivity (addingPreservesEqualityRight (succ a) (multiplicationNIsCommutative (succ a) b)) (transitivity (additionNIsCommutative (b *N (succ a)) (succ a)) refl ))))))))) productDistributes' : (a b c : ℕ) → (a +N b) *N c ≡ a *N c +N b *N c productDistributes' a b c rewrite multiplicationNIsCommutative (a +N b) c | productDistributes c a b | multiplicationNIsCommutative c a | multiplicationNIsCommutative c b = refl flipProductsWithinSum : (a b c : ℕ) → (c *N a +N c *N b ≡ a *N c +N b *N c) flipProductsWithinSum a b c = transitivity (addingPreservesEqualityRight (c *N b) (multiplicationNIsCommutative c a)) ((addingPreservesEqualityLeft (a *N c) (multiplicationNIsCommutative c b))) productDistributesRight : (a b c : ℕ) → (a +N b) *N c ≡ a *N c +N b *N c productDistributesRight a b c = transitivity (multiplicationNIsCommutative (a +N b) c) (transitivity (productDistributes c a b) (flipProductsWithinSum a b c)) multiplicationNIsAssociative : (a b c : ℕ) → (a *N (b *N c)) ≡ ((a *N b) *N c) multiplicationNIsAssociative zero b c = refl multiplicationNIsAssociative (succ a) b c = transitivity refl (transitivity refl (transitivity (applyEquality ((λ x → b *N c +N x)) (multiplicationNIsAssociative a b c)) (transitivity (equalityCommutative (productDistributesRight b (a *N b) c)) refl))) canAddZeroOnLeft : {a b : ℕ} → (a x