\import Algebra.Monoid
\import Algebra.Pointed.PointedHom
\import Equiv
\import Function.Meta
\import Logic
\import Paths
\import Paths.Meta
\import Set.Fin
\import Set.SetHom
\record SemigroupHom \extends SetHom {
\override Dom : Semigroup
\override Cod : Semigroup
| func-* {x y : Dom} : func (x * y) = func x * func y
}
\record MonoidHom \extends PointedHom, SemigroupHom {
\override Dom : Monoid
\override Cod : Monoid
\lemma func-pow {x : Dom} {n : Nat} : func (Monoid.pow x n) = Monoid.pow (func x) n \elim n
| 0 => func-ide
| suc n => func-* *> pmap (* _) func-pow
\lemma func-BigProd {l : Array Dom} : func (Monoid.BigProd l) = Monoid.BigProd (\lam j => func (l j)) \elim l
| nil => func-ide
| a :: l => func-* *> pmap (_ *) func-BigProd
\lemma func-LDiv {a b : Dom} (d : Monoid.LDiv a b) : Monoid.LDiv (func a) (func b) (func d.inv) \cowith
| inv-right => inv func-* *> pmap func d.inv-right
\lemma func-Inv {a : Dom} (d : Inv a) : Inv (func a) (func d.inv) \cowith
| inv-left => inv func-* *> pmap func d.inv-left *> func-ide
| inv-right => inv func-* *> pmap func d.inv-right *> func-ide
\lemma func-InvElem (e : Inv {Dom}) (e' : Inv {Cod}) (p : func e = e') : func e.inv = e'.inv
=> inv ide-left *> pmap (* _) (inv (pmap (_ *) p *> e'.inv-left)) *> *-assoc *> pmap (_ *) (inv func-* *> pmap func e.inv-right *> func-ide) *> ide-right
\lemma equiv-hom (e : IsEquiv func) : MonoidHom Cod Dom (IsEquiv.ret e) \cowith
| func-ide => IsEquiv.isInj e $ IsEquiv.f_ret e *> inv func-ide
| func-* => IsEquiv.isInj e $ IsEquiv.f_ret e *> inv (func-* *> pmap2 (*) (IsEquiv.f_ret e) (IsEquiv.f_ret e))
\lemma equiv-Inv (e : IsEquiv func) {a : Dom} (ai : Inv (func a)) : Inv a
=> transport Inv (IsEquiv.ret_f e) $ (equiv-hom e).func-Inv ai
} \where {
\func equals {M N : Monoid} {f g : MonoidHom M N} (p : \Pi (x : M) -> f x = g x) : f = g
=> exts p
\protected \func id {M : Monoid} : MonoidHom M M \cowith
| func x => x
| func-ide => idp
| func-* => idp
\protected \func \fixl 8 compose \alias \infixl 8 ∘ {M N K : Monoid} (g : MonoidHom N K) (f : MonoidHom M N) : MonoidHom M K \cowith
| func x => g (f x)
| func-ide => pmap g f.func-ide *> g.func-ide
| func-* => pmap g f.func-* *> g.func-*
\open Monoid(Inv)
}
\record AddMonoidHom \extends AddPointedHom {
\override Dom : AddMonoid
\override Cod : AddMonoid
| func-+ {x y : Dom} : func (x + y) = func x + func y
\lemma func-BigSum {l : Array Dom} : func (AddMonoid.BigSum l) = AddMonoid.BigSum (\lam j => func (l j)) \elim l
| nil => func-zro
| a :: l => func-+ *> pmap (_ +) func-BigSum
\lemma func-*n {n : Nat} {x : Dom} : func (n AddMonoid.*n x) = n AddMonoid.*n func x \elim n
| 0 => func-zro
| suc n => func-+ *> pmap (+ _) func-*n
} \where {
\use \coerce toMonoidHom (f : AddMonoidHom) : MonoidHom \cowith
| Dom => f.Dom
| Cod => f.Cod
| func => f
| func-* => func-+
| func-ide => func-zro
\protected \func id {M : AddMonoid} : AddMonoidHom M M \cowith
| func x => x
| func-zro => idp
| func-+ => idp
\protected \func \fixl 8 compose \alias \infixl 8 ∘ {A B C : AddMonoid} (g : AddMonoidHom B C) (f : AddMonoidHom A B) : AddMonoidHom A C \cowith
| func x => g (f x)
| func-zro => pmap g func-zro *> func-zro
| func-+ => pmap g func-+ *> func-+
\lemma func-FinSum {A B : AbMonoid} (f : AddMonoidHom A B) {J : FinSet} {a : J -> A} : f (A.FinSum a) = B.FinSum (\lam j => f (a j))
=> \case A.FinSum_char a \with {
| inP (e,q) => pmap f q *> f.func-BigSum *> inv (B.FinSum_char2 e)
}
}