\import Algebra.Group
\import Algebra.Meta
\import Algebra.Monoid
\import Algebra.Monoid.Sub
\import Function.Meta
\import Meta
\import Paths
\import Paths.Meta
\import Relation.Equivalence
\open Group
\class SubGroup \extends SubMonoid {
\override S : Group
| contains_inverse {x : S} : contains x -> contains (inverse x)
\func struct : Group \cowith
| Monoid => SubMonoid.struct
| inverse x => (inverse x.1, contains_inverse x.2)
| inverse-left => ext inverse-left
| inverse-right => ext inverse-right
\func equivalence : Equivalence S \cowith
| ~ x y => contains (inverse x * y)
| ~-reflexive => transportInv contains inverse-left contains_ide
| ~-symmetric c => transport contains (inverse_* *> pmap (_ *) inverse-isInv) (contains_inverse c)
| ~-transitive {x} {y} c1 c2 => rewriteEqF (inverse-right {S} {y}, ide-left) (contains_* c1 c2)
\func Cosets => Quotient (equivalence.~)
} \where {
\func cStruct {G : CGroup} (S : SubGroup G) : CGroup \cowith
| Group => S.struct
| *-comm => ext *-comm
}
\class DecSubGroup \extends SubGroup, DecSubMonoid {
\override S : Group
}
\class NormalSubGroup \extends SubGroup {
| isNormal (g : S) {h : S} : contains h -> contains (inverse g * h * g)
\lemma isNormal' (g : S) {h : S} (c : contains h) : contains (g * h * inverse g)
=> rewriteF inverse-isInv (isNormal (inverse g) c)
\func quotient : Group Cosets \cowith
| ide => in~ 1
| * (x y : Cosets) : Cosets \with {
| in~ g, in~ g' => in~ (g Group.* g')
| in~ g, ~-equiv x y r => ~-pequiv $ rewriteEq (inverse_*, inverse-left {S} {g}, ide-left) r
| ~-equiv x y r, in~ g => ~-pequiv $ rewriteEq inverse_* $ transport contains equation (isNormal g r)
}
| ide-left {x} => cases x \with {
| in~ a => pmap in~ ide-left
}
| ide-right {x} => cases x \with {
| in~ a => pmap in~ ide-right
}
| *-assoc {x} {y} {z} => cases (x,y,z) \with {
| in~ x, in~ y, in~ z => pmap in~ *-assoc
}
| inverse (x : Cosets) : Cosets \with {
| in~ g => in~ (Group.inverse g)
| ~-equiv x y r => ~-pequiv $ rewrite inverse-isInv $ rewriteEqF (inverse_*, inverse-isInv) $ contains_inverse $ rewriteEqF (inverse-right {S} {x}, ide-left) (isNormal' x r)
}
| inverse-left {x} => cases x \with {
| in~ a => pmap in~ inverse-left
}
| inverse-right {x} => cases x \with {
| in~ a => pmap in~ inverse-right
}
}
\class SubAddGroup \extends SubAddMonoid {
\override S : AddGroup
| contains_negative {x : S} : contains x -> contains (negative x)
\lemma contains_- {x y : S} : contains x -> contains y -> contains (x - y)
=> \lam cx cy => contains_+ cx (contains_negative cy)
\func struct : AddGroup \cowith
| AddMonoid => SubAddMonoid.struct
| negative x => (negative x.1, contains_negative x.2)
| negative-left => ext negative-left
| negative-right => ext negative-right
} \where {
\func abStruct {A : AbGroup} (S : SubAddGroup A) : AbGroup \cowith
| AddGroup => S.struct
| +-comm => ext +-comm
\func max {A : AddGroup} : SubAddGroup \cowith
| SubAddMonoid => SubAddMonoid.max {A}
| contains_negative _ => ()
}