GeneralisedArithmetic
{-# OPTIONS --without-K --safe #-}
module Data.Nat.GeneralisedArithmetic where
open import Data.Nat.Base using (β; zero; suc; _+_; _*_; _^_)
open import Data.Nat.Properties
using (+-comm; +-assoc; *-identityΛ‘; *-assoc)
open import Function.Base using (_ββ²_; _β_; id)
open import Level using (Level)
open import Relation.Binary.PropositionalEquality.Core
using (_β‘_; refl; cong; sym)
open import Relation.Binary.PropositionalEquality.Properties
using (module β‘-Reasoning)
open β‘-Reasoning
private
variable
a : Level
A : Set a
fold : A β (A β A) β β β A
fold z s zero = z
fold z s (suc n) = s (fold z s n)
iterate : (A β A) β A β β β A
iterate f x zero = x
iterate f x (suc n) = iterate f (f x) n
add : (0# : A) (1+ : A β A) β β β A β A
add 0# 1+ n z = fold z 1+ n
mul : (0# : A) (1+ : A β A) β (+ : A β A β A) β (β β A β A)
mul 0# 1+ _+_ n x = fold 0# (Ξ» s β x + s) n
fold-+ : β (z : A) (s : A β A) m {n} β
fold z s (m + n) β‘ fold (fold z s n) s m
fold-+ z s zero = refl
fold-+ z s (suc m) = cong s (fold-+ z s m)
fold-k : β (z : A) (s : A β A) {k} m β
fold k (s ββ²_) m z β‘ fold (k z) s m
fold-k z s zero = refl
fold-k z s (suc m) = cong s (fold-k z s m)
fold-* : β (z : A) (s : A β A) m {n} β
fold z s (m * n) β‘ fold z (fold id (s β_) n) m
fold-* z s zero = refl
fold-* z s (suc m) {n} = let +n = fold id (s ββ²_) n in begin
fold z s (n + m * n) β‘β¨ fold-+ z s n β©
fold (fold z s (m * n)) s n β‘β¨ cong (Ξ» z β fold z s n) (fold-* z s m) β©
fold (fold z +n m) s n β‘β¨ sym (fold-k _ s n) β©
fold z +n (suc m) β
fold-pull : β (z : A) (s : A β A) (g : A β A β A) (p : A)
(eqz : g z p β‘ p)
(eqs : β l β s (g l p) β‘ g (s l) p) β
β m β fold p s m β‘ g (fold z s m) p
fold-pull z s _ _ eqz _ zero = sym eqz
fold-pull z s g p eqz eqs (suc m) = begin
s (fold p s m) β‘β¨ cong s (fold-pull z s g p eqz eqs m) β©
s (g (fold z s m) p) β‘β¨ eqs (fold z s m) β©
g (s (fold z s m)) p β
iterate-is-fold : β (z : A) s m β fold z s m β‘ iterate s z m
iterate-is-fold z s zero = refl
iterate-is-fold z s (suc m) = begin
fold z s (suc m) β‘β¨ cong (fold z s) (+-comm 1 m) β©
fold z s (m + 1) β‘β¨ fold-+ z s m β©
fold (s z) s m β‘β¨ iterate-is-fold (s z) s m β©
iterate s (s z) m β
id-is-fold : β m β fold zero suc m β‘ m
id-is-fold zero = refl
id-is-fold (suc m) = cong suc (id-is-fold m)
+-is-fold : β m {n} β fold n suc m β‘ m + n
+-is-fold zero = refl
+-is-fold (suc m) = cong suc (+-is-fold m)
*-is-fold : β m {n} β fold zero (n +_) m β‘ m * n
*-is-fold zero = refl
*-is-fold (suc m) {n} = cong (n +_) (*-is-fold m)
^-is-fold : β {m} n β fold 1 (m *_) n β‘ m ^ n
^-is-fold zero = refl
^-is-fold {m} (suc n) = cong (m *_) (^-is-fold n)
*+-is-fold : β m n {p} β fold p (n +_) m β‘ m * n + p
*+-is-fold m n {p} = begin
fold p (n +_) m β‘β¨ fold-pull _ _ _+_ p refl
(Ξ» l β sym (+-assoc n l p)) m β©
fold 0 (n +_) m + p β‘β¨ cong (_+ p) (*-is-fold m) β©
m * n + p β
^*-is-fold : β m n {p} β fold p (m *_) n β‘ m ^ n * p
^*-is-fold m n {p} = begin
fold p (m *_) n β‘β¨ fold-pull _ _ _*_ p (*-identityΛ‘ p)
(Ξ» l β sym (*-assoc m l p)) n β©
fold 1 (m *_) n * p β‘β¨ cong (_* p) (^-is-fold n) β©
m ^ n * p β