agda2hs-1.3: lib/Haskell/Law/Num/Word.agda
{-# OPTIONS --allow-unsolved-metas #-}
module Haskell.Law.Num.Word where
open import Haskell.Prim
open import Haskell.Prim.Num
open import Haskell.Prim.Word
open Haskell.Prim.Word.WordInternal
open import Haskell.Law.Equality
open import Haskell.Law.Function
open import Haskell.Law.Nat
open import Haskell.Law.Num.Def
open import Haskell.Law.Num.Nat
open Num iNumNat renaming (_+_ to _+ⁿ_; _*_ to _*ⁿ_)
open Num iNumWord renaming (_+_ to _+ʷ_; _*_ to _*ʷ_)
postulate
-- This is a reasonable axiom because there are more natural numbers than
-- integer. More precisely, Words denote a finite subset of Integers.
-- This means, there is am embedding of Words into Integers as stated by
-- this axiom.
n2w∘w2n≡id : ∀ (x : Word) → n2w (w2n x) ≡ x
-- Conversion of natural numbers to words is invertible as long as the
-- natural is within word bounds.
w2n∘n2w≡id : ∀ (x : Nat) → x ≤ 2⁶⁴ → w2n (n2w x) ≡ x
-- Definitions of word arithmetics are based on conversions to Nats.
-- That conversion must be homomorphic w.r.t. to addition and multiplication
-- to not break their properties.
w2n-+-hom : Homomorphism₂ _+ʷ_ _+ⁿ_ w2n
w2n-*-hom : Homomorphism₂ _*ʷ_ _*ⁿ_ w2n
-- 2⁶⁴ is the upper bound of the ring that forms Words in Nats.
max-int≡0 : n2w 2⁶⁴ ≡ 0
-- Words are bounded. They can never be larger than 2⁶⁴.
bounded : ∀ (x : Word) → w2n x ≤ 2⁶⁴
open MonoidEmbedding₂
+-wordsAsNats : MonoidEmbedding₂ addWord addNat w2n n2w 0 0
Embedding₂.hom (embedding +-wordsAsNats) = w2n-+-hom
Embedding₂.embed (embedding +-wordsAsNats) = n2w∘w2n≡id
0-hom +-wordsAsNats = refl
*-wordsAsNats : MonoidEmbedding₂ mulWord mulNat w2n n2w 1 1
Embedding₂.hom (embedding *-wordsAsNats) = w2n-*-hom
Embedding₂.embed (embedding *-wordsAsNats) = n2w∘w2n≡id
0-hom *-wordsAsNats = refl
addWord-idˡ : Identityˡ addWord 0
addWord-idˡ = map-idˡ addWord addNat w2n n2w 0 0 +-wordsAsNats addNat-idˡ
addWord-idʳ : Identityʳ addWord 0
addWord-idʳ = map-idʳ addWord addNat w2n n2w 0 0 +-wordsAsNats addNat-idʳ
addWord-comm : Commutative addWord
addWord-comm = map-comm addWord addNat w2n n2w (embedding +-wordsAsNats) addNat-comm
addWord-assoc : Associative addWord
addWord-assoc = map-assoc addWord addNat w2n n2w (embedding +-wordsAsNats) addNat-assoc
mulWord-comm : Commutative mulWord
mulWord-comm = map-comm mulWord mulNat w2n n2w (embedding *-wordsAsNats) mulNat-comm
mulWord-assoc : Associative mulWord
mulWord-assoc = map-assoc mulWord mulNat w2n n2w (embedding *-wordsAsNats) mulNat-assoc
mulWord-idˡ : Identityˡ mulWord 1
mulWord-idˡ = map-idˡ mulWord mulNat w2n n2w 1 1 *-wordsAsNats mulNat-idˡ
mulWord-idʳ : Identityʳ mulWord 1
mulWord-idʳ = map-idʳ mulWord mulNat w2n n2w 1 1 *-wordsAsNats mulNat-idʳ
mulWord-distributeˡ-addWord : Distributiveˡ addWord mulWord
mulWord-distributeˡ-addWord = map-distributeˡ addWord addNat mulWord mulNat w2n n2w n2w∘w2n≡id w2n-+-hom w2n-*-hom mulNat-distributeˡ-addNat
mulWord-distributeʳ-addWord : Distributiveʳ addWord mulWord
mulWord-distributeʳ-addWord = map-distributeʳ addWord addNat mulWord mulNat w2n n2w n2w∘w2n≡id w2n-+-hom w2n-*-hom mulNat-distributeʳ-addNat
neg-inv-word : ∀ (x : Word) → addWord x (negateWord x) ≡ 0
neg-inv-word x =
x + negateWord x ≡⟨⟩
n2w (w2n x + w2n (negateWord x)) ≡⟨⟩
n2w (w2n x + w2n (n2w (monusNat 2⁶⁴ (w2n x)))) ≡⟨ cong n2w (cong (w2n x +_) (w2n∘n2w≡id (monusNat 2⁶⁴ (w2n x)) (y-x≤y (w2n x) 2⁶⁴))) ⟩
n2w (w2n x + monusNat 2⁶⁴ (w2n x)) ≡⟨ cong n2w (x+[y-x]≡y (w2n x) 2⁶⁴ (bounded x)) ⟩
n2w 2⁶⁴ ≡⟨ max-int≡0 ⟩
0 ∎
instance
open IsLawfulNum
iLawfulNumWord : IsLawfulNum Word
+-assoc iLawfulNumWord = addWord-assoc
+-comm iLawfulNumWord = addWord-comm
+-idˡ iLawfulNumWord = λ x → addWord-idˡ x
+-idʳ iLawfulNumWord = λ x → addWord-idʳ x
neg-inv iLawfulNumWord = λ x → neg-inv-word x
*-assoc iLawfulNumWord = mulWord-assoc
*-idˡ iLawfulNumWord = λ x → mulWord-idˡ x
*-idʳ iLawfulNumWord = λ x → mulWord-idʳ x
distributeˡ iLawfulNumWord = mulWord-distributeˡ-addWord
distributeʳ iLawfulNumWord = mulWord-distributeʳ-addWord