module Algebra.Ring.Module.Free {β} (R : Ring β) where
Free modulesπ
For a finite set of generators, we can define free modules very directly: for example, using vectors. For infinite sets, this definition does not work as well: rings do not admit infinite sums, so we would need a way to βtameβ the vectors so only a finite amount of information needs to be summed at a time. The usual definition, of being zero in all but finitely many indices, is problematic since we can not (unless the indexing set admits decidable equality) define the map .
Note: even if is not, strictly speaking, built on an underlying (sub)set of functions into , we will stick to the exponential notation for definiteness.
Fortunately, free objects have a very straightforward definition in type theory: they are initial objects in certain categories of algebras, so they can be presented as1 inductive types.
data Free-mod {ββ²} (A : Type ββ²) : Type (β β ββ²) where inc : A β Free-mod A _+_ : Free-mod A β Free-mod A β Free-mod A neg : Free-mod A β Free-mod A 0m : Free-mod A _Β·_ : β R β β Free-mod A β Free-mod A
The free module on is generated by elements of (the inc) constructor, the operations of an Abelian group (which we write with _+_), together with a scalar multiplication operation . The equations imposed are precisely those necessary to make _+_ into an abelian group, and the scalar multiplication into an action by . We also add a squash constructor, since modules must have an underlying set.
+-comm : β x y β x + y β‘ y + x +-assoc : β x y z β x + (y + z) β‘ (x + y) + z +-invl : β x β neg x + x β‘ 0m +-idl : β x β 0m + x β‘ x Β·-id : β x β R.1r Β· x β‘ x Β·-distribl : β x y z β x Β· (y + z) β‘ x Β· y + x Β· z Β·-distribr : β x y z β (x R.+ y) Β· z β‘ x Β· z + y Β· z Β·-assoc : β x y z β x Β· y Β· z β‘ (x R.* y) Β· z squash : is-set (Free-mod A)
In passing, we define a record to package together the data of a predicate on free modules: as long as it is prop-valued, we can prove something for all of by treating the group operations, the ring action, and the generators.
record Free-elim-prop {ββ² ββ²β²} {A : Type ββ²} (P : Free-mod A β Type ββ²β²) : Type (β β ββ² β ββ²β²) where no-eta-equality field has-is-prop : β x β is-prop (P x) P-0m : P 0m P-neg : β x β P x β P (neg x) P-inc : β x β P (inc x) P-Β· : β x y β P y β P (x Β· y) P-+ : β x y β P x β P y β P (x + y) elim : β x β P x
elim (inc x) = P-inc x elim (x Β· y) = P-Β· x y (elim y) elim (x + y) = P-+ x y (elim x) (elim y) elim (neg x) = P-neg x (elim x) elim 0m = P-0m elim (+-comm x y i) = is-propβpathp (Ξ» j β has-is-prop (+-comm x y j)) (P-+ x y (elim x) (elim y)) (P-+ y x (elim y) (elim x)) i elim (+-assoc x y z i) = is-propβpathp (Ξ» j β has-is-prop (+-assoc x y z j)) (P-+ _ _ (elim x) (P-+ _ _ (elim y) (elim z))) (P-+ _ _ (P-+ _ _ (elim x) (elim y)) (elim z)) i elim (+-invl x i) = is-propβpathp (Ξ» j β has-is-prop (+-invl x j)) (P-+ _ _ (P-neg _ (elim x)) (elim x)) P-0m i elim (+-idl x i) = is-propβpathp (Ξ» j β has-is-prop (+-idl x j)) (P-+ _ _ P-0m (elim x)) (elim x) i elim (Β·-id x i) = is-propβpathp (Ξ» j β has-is-prop (Β·-id x j)) (P-Β· R.1r _ (elim x)) (elim x) i elim (Β·-distribl x y z i) = is-propβpathp (Ξ» j β has-is-prop (Β·-distribl x y z j)) (P-Β· x _ (P-+ _ _ (elim y) (elim z))) (P-+ _ _ (P-Β· x _ (elim y)) (P-Β· x _ (elim z))) i elim (Β·-distribr x y z i) = is-propβpathp (Ξ» j β has-is-prop (Β·-distribr x y z j )) (P-Β· (x R.+ y) _ (elim z)) (P-+ _ _ (P-Β· x _ (elim z)) (P-Β· y _ (elim z))) i elim (Β·-assoc x y z i) = is-propβpathp (Ξ» j β has-is-prop (Β·-assoc x y z j)) (P-Β· x (y Β· z) (P-Β· y _ (elim z))) (P-Β· (x R.* y) z (elim z)) i elim (squash x y p q i j) = is-propβsquarep (Ξ» i j β has-is-prop (squash x y p q i j)) (Ξ» _ β elim x) (Ξ» j β elim (p j)) (Ξ» j β elim (q j)) (Ξ» _ β elim y) i j
Iβll leave the definition of the group, Abelian group, and
-module
structures on
in this <details>
tag, since theyβre not particularly interesting. For every operation
and law, we simply use the corresponding constructors.
open Module-on hiding (_+_) open make-module hiding (_+_) Module-on-free-mod : β {ββ²} (A : Type ββ²) β Module-on R (Free-mod A) Module-on-free-mod A = to-module-on mk module Module-on-free-mod where mk : make-module R (Free-mod A) mk .has-is-set = squash mk .make-module._+_ = _+_ mk .inv = neg mk .0g = 0m mk .make-module.+-assoc = Free-mod.+-assoc mk .make-module.+-invl = Free-mod.+-invl mk .make-module.+-idl = Free-mod.+-idl mk .make-module.+-comm = Free-mod.+-comm mk ._β_ = _Β·_ mk .β-distribl = Free-mod.Β·-distribl mk .β-distribr = Free-mod.Β·-distribr mk .β-assoc x y z = Free-mod.Β·-assoc x y z mk .β-id = Free-mod.Β·-id Free-Mod : β {ββ²} β Type ββ² β Module R (β β ββ²) Free-Mod T = to-module (Module-on-free-mod.mk T) open Functor
fold-free-mod : β {β ββ²} {A : Type β} (N : Module R ββ²) β (A β β N β) β Linear-map (Free-Mod A) N fold-free-mod {A = A} N f = go-linear module fold-free-mod where private module N = Module-on (N .snd)
The endless constructors of Free-mod are powerless in the face of a function from the generators into the underlying type of an actual -module . Each operation is mapped to the corresponding operation on , so the path constructors are also handled by the witnesses that is an actual module. This function, annoying though it may be to write, is definitionally a linear map β saving us a bit of effort.
-- Rough: go : Free-mod A β β N β go (inc x) = f x go (x Β· y) = x N.β go y go (x + y) = go x N.+ go y go (neg x) = N.- (go x) go 0m = N.0g go (+-comm x y i) = N.+-comm {go x} {go y} i go (+-assoc x y z i) = N.+-assoc {go x} {go y} {go z} i go (+-invl x i) = N.+-invl {go x} i go (+-idl x i) = N.+-idl {go x} i go (Β·-id x i) = N.β-id (go x) i go (Β·-distribl x y z i) = N.β-distribl x (go y) (go z) i go (Β·-distribr x y z i) = N.β-distribr x y (go z) i go (Β·-assoc x y z i) = N.β-assoc x y (go z) i go (squash a b p q i j) = N.has-is-set (go a) (go b) (Ξ» i β go (p i)) (Ξ» i β go (q i)) i j go-linear : Linear-map (Free-Mod A) N go-linear .map = go go-linear .lin .linear r s t = refl {-# DISPLAY fold-free-mod.go = fold-free-mod #-} {-# DISPLAY fold-free-mod.go-linear = fold-free-mod #-}
To prove that free modules have the expected universal property, it remains to show that if , then . Since weβre eliminating into a proposition, all we have to handle are the operation constructors, which is.. inductive, but manageable. Iβll leave the computation here if youβre interested:
open make-left-adjoint make-free-module : β {ββ²} β make-left-adjoint (Forget-module R (β β ββ²)) make-free-module {ββ²} = go where go : make-left-adjoint (Forget-structure (R-Mod-structure R)) go .free x = Free-Mod β£ x β£ go .unit x = Free-mod.inc go .universal {y = y} f = linear-mapβhom (fold-free-mod {β = β β ββ²} y f) go .commutes f = refl go .unique {y = y} {f = f} {g = g} p = Homomorphism-path {β β ββ²} (Free-elim-prop.elim m) where open Free-elim-prop module g = Linear-map (homβlinear-map g) module y = Module-on (y .snd) fold = fold-free-mod y f .map m : Free-elim-prop (Ξ» a β fold-free-mod y f .map a β‘ g.map a) m .has-is-prop x = hlevel! m .P-Β· x y p = x y.β fold y β‘β¨ ap (x y.β_) p β©β‘ x y.β g.map y β‘Λβ¨ g.pres-β _ _ β©β‘Λ g.map (x Β· y) β m .P-0m = sym g.pres-0 m .P-+ x y p q = fold x y.+ fold y β‘β¨ apβ y._+_ p q β©β‘ g.map x y.+ g.map y β‘Λβ¨ g.pres-+ _ _ β©β‘Λ g.map (x + y) β m .P-neg x p = y.- (fold x) β‘β¨ ap y.-_ p β©β‘ y.- (g.map x) β‘Λβ¨ g.pres-neg β©β‘Λ g.map (neg x) β m .P-inc x = p $β x
After that calculation, we can β¨ just β¨ conclude that Free-module has the right universal property: that is, we can rearrange the proof above into the form of a functor and an adjunction.
Free-module : β {ββ²} β Functor (Sets (β β ββ²)) (R-Mod R (β β ββ²)) Free-module {ββ² = ββ²} = make-left-adjoint.to-functor (make-free-module {ββ² = ββ²}) Freeβ£Forget : β {ββ²} β Free-module {ββ²} β£ Forget-module R (β β ββ²) Freeβ£Forget {ββ²} = make-left-adjoint.to-left-adjoint (make-free-module {ββ² = ββ²})
open Free-elim-prop equal-on-basis : β {βb βg} {T : Type βb} (M : Module R βg) β {f g : Linear-map (Free-Mod T) M} β ((x : T) β f .map (inc x) β‘ g .map (inc x)) β f β‘ g equal-on-basis M {f} {g} p = Linear-map-path $ Free-elim-prop.elim Ξ» where .has-is-prop x β M .fst .is-tr _ _ .P-0m β f.pres-0 β sym g.pres-0 .P-neg x Ξ± β f.pres-neg Β·Β· ap M.-_ Ξ± Β·Β· sym g.pres-neg .P-inc β p .P-Β· x y Ξ± β f.pres-β _ _ Β·Β· ap (x M.β_) Ξ± Β·Β· sym (g.pres-β _ _) .P-+ x y Ξ± Ξ² β f.pres-+ _ _ Β·Β· apβ M._+_ Ξ± Ξ² Β·Β· sym (g.pres-+ _ _) where module f = Linear-map f module g = Linear-map g module M = Module-on (M .snd) equal-on-basisβ² : β {βb βg} {T : Type βb} {G : Type βg} (M : Module-on R G) β (let module M = Module-on M) β {f : Free-mod T β G} β (β r x y β f (r Β· x + y) β‘ r M.β f x M.+ f y) β {g : Free-mod T β G} β (β r x y β g (r Β· x + y) β‘ r M.β g x M.+ g y) β ((x : T) β f (inc x) β‘ g (inc x)) β f β‘ g equal-on-basisβ² M l1 l2 p = ap map $ equal-on-basis (el _ (Module-on.has-is-set M) , M) {f = record { lin = record { linear = l1 } }} {g = record { lin = record { linear = l2 } }} p module _ (cring : is-commutative-ring R) where open Algebra.Ring.Module.Multilinear R cring multilinear-extension : β {n} {ββ} {ββ : Fin (suc n) β Level} {Ms : (i : Fin (suc n)) β Type (ββ i)} {N : Module R ββ} β (f : ArrαΆ Ms β N β) β Multilinear-map (suc n) (Ξ» i β Free-Mod (Ms i)) N multilinear-extension {zero} {N = N} f = 1-linear-map (fold-free-mod N f) multilinear-extension {suc n} f = Uncurry.from $ fold-free-mod _ Ξ» x β multilinear-extension (f x) multi-equal-on-bases : β {n} {ββ} {ββ : Fin n β Level} {Ms : (i : Fin n) β Type (ββ i)} {N : Module R ββ} β {f g : Multilinear-map n (Ξ» i β Free-Mod (Ms i)) N} β (β (as : Ξ αΆ Ms) β applyαΆ (f .map) (mapβ (Ξ» _ β inc) as) β‘ applyαΆ (g .map) (mapβ (Ξ» _ β inc) as)) β f β‘ g multi-equal-on-bases {n = zero} p = Multilinear-map-path (p tt) multi-equal-on-bases {n = suc n} {f = f} {g} p = Uncurry.injective $ equal-on-basis _ Ξ» x β multi-equal-on-bases Ξ» as β p (x , as)
truncated, higherβ©οΈ