module Algebra.Field.Properties where open import Level open import Function open import Data.Nat hiding (_+_; _*_; _^_; NonZero; nonZero; _⊔_) open import Data.Integer hiding (_+_; _*_; _^_; NonZero; nonZero; _⊔_) open import Data.Product open import Data.Vec open import Algebra open import Algebra.Field.Base open import Algebra.Ring.Properties as R open import Algebra.CommRing.Properties as CR open import Relation.Binary as RB hiding (Decidable) open import Relation.Unary as RU hiding (Decidable) open import Relation.Nullary open import Relation.Nullary.Decidable.Core module FieldUnits {ℓ ℓ'} (field' : Field ℓ ℓ') where open Field field' renaming (Carrier to A) semiRing : RawSemiring _ _ semiRing = record { Carrier = A ; _≈_ = _≈_ ; _+_ = _+_ ; _*_ = _*_ ; 0# = 0# ; 1# = 1# } open import Algebra.Definitions.RawSemiring semiRing open import Relation.Binary.Reasoning.Setoid setoid open CR.Units commutativeRing private A≢0 = Σ[ a ∈ A ] (a ≉ 0#) variable n : ℕ _[_]^_ : (a : A) → (a≉0 : a ≉ 0#) → ℤ → A a [ a≉0 ]^ (+ n) = a ^ n a [ a≉0 ]^ -[1+ n ] = inv a a≉0 ^ ℕ.suc n _^n_ : A≢0 → ℕ → A≢0 (a , a≉0) ^n n = (a ^ n) , a^n≉0 where a^n·a^-n≡1' = ^-presUnit a n (_ , hasInverse a a≉0) a^n = a ^ n a^-n = a^n·a^-n≡1' .proj₁ a^n·a^-n≡1 : (a^n * a^-n) ≈ 1# a^n·a^-n≡1 = a^n·a^-n≡1' .proj₂ a^n≉0 : a^n ≉ 0# a^n≉0 a^n≡0 = 0≢1 (trans (sym (trans (*-congʳ a^n≡0) (0LeftAnnihilates _))) a^n·a^-n≡1) _^z_ : A≢0 → ℤ → A≢0 a ^z (+ n) = a ^n n a@(a' , a≉0) ^z -[1+ n ] = (a⁻¹ , a⁻¹≉0) ^n (ℕ.suc n) where a⁻¹ = inv a' a≉0 a⁻¹≉0 : a⁻¹ ≉ 0# a⁻¹≉0 a⁻¹≡0 = 0≢1 (trans (sym (trans (*-congˡ a⁻¹≡0) (0RightAnnihilates _))) (hasInverse a' a≉0)) _*n_ : A≢0 → A≢0 → A≢0 p@(a , a≉0) *n q@(b , b≉0) = (a * b) , a*b≉0 where b⁻¹ = inv b b≉0 b*b⁻¹≡1 = hasInverse b b≉0 a*b≉0 : (a * b) ≉ 0# a*b≉0 a*b≈0 = a≉0 (begin a ≈˘⟨ *-identityʳ _ ⟩ a * 1# ≈˘⟨ *-congˡ b*b⁻¹≡1 ⟩ a * (b * b⁻¹) ≈˘⟨ *-assoc _ _ _ ⟩ a * b * b⁻¹ ≈⟨ *-congʳ a*b≈0 ⟩ 0# * b⁻¹ ≈⟨ 0LeftAnnihilates _ ⟩ 0# ∎) foldr≉0 : (a : A≢0) (xs : Vec A≢0 n) → foldr _ (λ x y → x .proj₁ * y) (a .proj₁) xs ≉ 0# foldr≉0 (_ , a≉0) [] = a≉0 foldr≉0 a (b ∷ xs) = (b *n (_ , foldr≉0 a xs)) .proj₂ record NonZero (a : A) : Set ℓ' where constructor nonZeroC field nonZero : a ≉ 0# mulVec : Vec A≢0 n → A≢0 mulVec xs = _ , (foldr≉0 (1# , (0≢1 ∘ sym)) xs) module DiscA (disc : RB.Decidable _≈_) where decP≉0 : (p : A) → Dec (NonZero p) decP≉0 p with disc p 0# ... | yes p≈0 = no λ where (nonZeroC p≉0) → p≉0 p≈0 ... | no p≉0 = yes (nonZeroC p≉0) private data Decidable {ℓ} {ℓ'} {A : Set ℓ} (P : A → Set ℓ') : Set (ℓ ⊔ ℓ') where isDec : (∀ a → Dec (P a)) → Decidable P data AllVec {ℓ} {ℓ'} {A : Set ℓ} (P : A → Set ℓ') : Vec A n → Set (ℓ ⊔ ℓ') where emp : AllVec P [] consVec : {x : A} (p : P x) {xs : Vec A n} (allXS : AllVec P xs) → AllVec P (x ∷ xs) variable ℓ'' : Level A' B C D : Set ℓ'' B' B'' : (a : A) → Set ℓ'' DecAll : Decidable B' → (xs : Vec A n) → Dec (AllVec B' xs) DecAll P [] = yes emp DecAll P'@(isDec P) (x ∷ xs) with P x | DecAll P' xs ... | no ¬p | _ = no (λ where (consVec p allXs) → ¬p p) ... | yes p | no ¬q = no (λ where (consVec p allXs) → ¬q allXs) ... | yes p | yes q = yes (consVec p q) instance toDecAll : ⦃ decB : Decidable B' ⦄ {xs : Vec A n} {decVec : True (DecAll decB xs)} → AllVec B' xs toDecAll ⦃ decB = decB ⦄ {[]} {decVec} = emp toDecAll ⦃ decB = P'@(isDec P) ⦄ {x ∷ xs} {decVec} with P x | DecAll P' xs ... | yes x | yes xs = consVec x xs DecNonZero : Decidable NonZero DecNonZero = isDec decP≉0 vec→vec≉0 : (xs : Vec A n) ⦃ xs≉0 : AllVec NonZero xs ⦄ → Vec A≢0 n vec→vec≉0 [] = [] vec→vec≉0 (x ∷ xs) ⦃ consVec (nonZeroC nonZero) xs≉0 ⦄ = (x , nonZero) ∷ vec→vec≉0 xs ⦃ xs≉0 ⦄