This files defines typeclasses for monoids in the category of Coq types and functions
Just like in the category of sets, where
Every set can be made into a comonoid in Set (with the cartesian product) in a unique way.
comonoids in Coq's category are not particularly varied: there is one comonoid on each type.
From Tealeaves Require Export Prelude. #[local] Generalizable Variables x y z a A B W M R. (** * Monoids *) (**********************************************************************) (** ** Operational typeclasses *) (**********************************************************************) Class Monoid_op (A: Type) := monoid_op: A -> A -> A. Class Monoid_unit (A: Type) := monoid_unit: A. #[global] Arguments monoid_op {A}%type_scope {Monoid_op}. #[global] Arguments monoid_unit A%type_scope {Monoid_unit}. #[local] Notation "'Ƶ'" := (monoid_unit _): tealeaves_scope. #[local] Infix "●" := monoid_op (at level 60): tealeaves_scope. (** ** Monoid typeclass *) (**********************************************************************) Class Monoid (M: Type) {op: Monoid_op M} {unit: Monoid_unit M} := { monoid_assoc: `((x ● y) ● z = x ● (y ● z)); monoid_id_r: `(x ● Ƶ = x); monoid_id_l: `(Ƶ ● x = x); }.
A homomorphism \(\phi: A \to B\) is a function which satisfies
(** ** Monoid homomorphsims *) (**********************************************************************) Class Monoid_Morphism (src tgt: Type) `{src_op: Monoid_op src} `{src_unit: Monoid_unit src} `{tgt_op: Monoid_op tgt} `{tgt_unit: Monoid_unit tgt} (ϕ: src -> tgt) := { monmor_src: Monoid src; monmor_tgt: Monoid tgt; monmor_unit: ϕ Ƶ = Ƶ; monmor_op: `(ϕ (a1 ● a2) = ϕ a1 ● ϕ a2); }. Section monoid_morphism_composition. Context (M1 M2 M3: Type) `{Monoid M1} `{Monoid M2} `{Monoid M3} (ϕ1: M1 -> M2) (ϕ2: M2 -> M3) `{! Monoid_Morphism M1 M2 ϕ1 } `{! Monoid_Morphism M2 M3 ϕ2 }.M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2Monoid_Morphism M1 M3 (ϕ2 ∘ ϕ1)M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2Monoid_Morphism M1 M3 (ϕ2 ∘ ϕ1)M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2(ϕ2 ∘ ϕ1) Ƶ = ƵM1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2forall a1 a2 : M1, (ϕ2 ∘ ϕ1) (a1 ● a2) = (ϕ2 ∘ ϕ1) a1 ● (ϕ2 ∘ ϕ1) a2M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2ϕ2 (ϕ1 Ƶ) = ƵM1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2forall a1 a2 : M1, ϕ2 (ϕ1 (a1 ● a2)) = ϕ2 (ϕ1 a1) ● ϕ2 (ϕ1 a2)M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2ϕ2 (ϕ1 Ƶ) = ƵM1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2ϕ2 Ƶ = Ƶreflexivity.M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2Ƶ = ƵM1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2forall a1 a2 : M1, ϕ2 (ϕ1 (a1 ● a2)) = ϕ2 (ϕ1 a1) ● ϕ2 (ϕ1 a2)M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2
a1, a2: M1ϕ2 (ϕ1 (a1 ● a2)) = ϕ2 (ϕ1 a1) ● ϕ2 (ϕ1 a2)M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2
a1, a2: M1ϕ2 (ϕ1 a1 ● ϕ1 a2) = ϕ2 (ϕ1 a1) ● ϕ2 (ϕ1 a2)reflexivity. Qed. End monoid_morphism_composition. (** ** Some Rudimentary Automation *) (**********************************************************************) Ltac simpl_monoid := repeat rewrite monoid_id_r; repeat rewrite monoid_id_l; repeat rewrite monoid_assoc. Tactic Notation "simpl_monoid" "in" ident(H) := repeat rewrite monoid_id_r in H; repeat rewrite monoid_id_l in H; repeat rewrite monoid_assoc in H. Tactic Notation "simpl_monoid" "in" "*" := repeat rewrite monoid_id_r in *; repeat rewrite monoid_id_l in *; repeat rewrite monoid_assoc in *. (** * Monoid Constructions *) (**********************************************************************) (** ** Cartesian Product of Monoids *) (**********************************************************************) Section product_monoid. Context `{Monoid A, Monoid B}. #[export] Instance Monoid_unit_product: Monoid_unit (A * B) := (Ƶ, Ƶ). #[export] Instance Monoid_op_product: Monoid_op (A * B) := fun '(a1, b1) '(a2, b2) => (a1 ● a2, b1 ● b2). #[export] Program Instance Monoid_product: Monoid (A * B). Solve Obligations with (intros; destruct_all_pairs; unfold transparent tcs; cbn beta iota; now simpl_monoid). End product_monoid. (** ** The Opposite Monoid *) (**********************************************************************) #[local] Instance Monoid_op_Opposite {M} (op: Monoid_op M): Monoid_op M := fun m1 m2 => m2 ● m1.M1, M2, M3: Type
op: Monoid_op M1
unit0: Monoid_unit M1
H: Monoid M1
op0: Monoid_op M2
unit1: Monoid_unit M2
H0: Monoid M2
op1: Monoid_op M3
unit2: Monoid_unit M3
H1: Monoid M3
ϕ1: M1 -> M2
ϕ2: M2 -> M3
Monoid_Morphism0: Monoid_Morphism M1 M2 ϕ1
Monoid_Morphism1: Monoid_Morphism M2 M3 ϕ2
a1, a2: M1ϕ2 (ϕ1 a1) ● ϕ2 (ϕ1 a2) = ϕ2 (ϕ1 a1) ● ϕ2 (ϕ1 a2)M: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid MMonoid MM: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid MMonoid MM: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid M
x, y, z: Mz ● (y ● x) = (z ● y) ● xM: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid M
x: MƵ ● x = xM: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid M
x: Mx ● Ƶ = xnow rewrite monoid_assoc.M: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid M
x, y, z: Mz ● (y ● x) = (z ● y) ● xnow rewrite monoid_id_l.M: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid M
x: MƵ ● x = xnow rewrite monoid_id_r. Qed.M: Type
unit: Monoid_unit M
op: Monoid_op M
Monoid0: Monoid M
x: Mx ● Ƶ = xM: Type
op: Monoid_op MMonoid_op_Opposite (Monoid_op_Opposite op) = opreflexivity. Qed. (** * Increment and Pre-increment *) (**********************************************************************) (** ** The <<incr>> Operation *) (**********************************************************************) Section incr. Context `{Monoid W}. (* It sometimes useful to have this curried operation, the composition of [strength] and [join]. *) Definition incr {A: Type}: W -> W * A -> W * A := fun w2 '(w1, a) => (w2 ● w1, a).M: Type
op: Monoid_op MMonoid_op_Opposite (Monoid_op_Opposite op) = opW: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Typeincr Ƶ = idW: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Typeincr Ƶ = idW: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
w: W
a: Aincr Ƶ (w, a) = id (w, a)now simpl_monoid. Qed.W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
w: W
a: A(Ƶ ● w, a) = id (w, a)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Typeforall w1 w2 : W, incr w2 ∘ incr w1 = incr (w2 ● w1)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Typeforall w1 w2 : W, incr w2 ∘ incr w1 = incr (w2 ● w1)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
w1, w2: Wincr w2 ∘ incr w1 = incr (w2 ● w1)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
w1, w2, w: W
a: A(incr w2 ∘ incr w1) (w, a) = incr (w2 ● w1) (w, a)now simpl_monoid. Qed. End incr. (** ** The <<preincr>> Operation *) (**********************************************************************) Section preincr. Context `{Monoid W}. Definition preincr {A B: Type} (f: W * A -> B) (w: W) := f ∘ incr w. #[local] Infix "⦿" := preincr (at level 30): tealeaves_scope.W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A: Type
w1, w2, w: W
a: A(w2 ● (w1 ● w), a) = ((w2 ● w1) ● w, a)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Typeforall f : W * A -> B, f ⦿ Ƶ = fW: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Typeforall f : W * A -> B, f ⦿ Ƶ = fW: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> Bf ⦿ Ƶ = fnow rewrite incr_zero. Qed.W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> Bf ∘ incr Ƶ = fW: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Typeforall (f : W * A -> B) (w1 w2 : W), (f ⦿ w1) ⦿ w2 = f ⦿ (w1 ● w2)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Typeforall (f : W * A -> B) (w1 w2 : W), (f ⦿ w1) ⦿ w2 = f ⦿ (w1 ● w2)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> B
w1, w2: W(f ⦿ w1) ⦿ w2 = f ⦿ (w1 ● w2)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> B
w1, w2: Wf ∘ incr w1 ∘ incr w2 = f ∘ incr (w1 ● w2)now rewrite incr_incr. Qed.W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B: Type
f: W * A -> B
w1, w2: Wf ∘ (incr w1 ∘ incr w2) = f ∘ incr (w1 ● w2)W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> C
f: W * A -> B
w: W(g ∘ f) ⦿ w = g ∘ f ⦿ wreflexivity. Qed. End preincr. From Coq Require Export Relations Classes.RelationClasses. (** * Preordered Monoids *) (**********************************************************************) Class PreOrderedMonoidLaws (M: Type) (R: relation M) (op: Monoid_op M) (unit: Monoid_unit M) := { pom_mono_l: `(R x y -> R (z ● x) (z ● y)); pom_mono_r: `(R x y -> R (x ● z) (y ● z)); }. Class PreOrderedMonoid (M: Type) (R: relation M) {op: Monoid_op M} {unit: Monoid_unit M} := { pom_monoid :> Monoid M; pom_order :> PreOrder R; pom_laws :> PreOrderedMonoidLaws M R op unit; }. Class PreOrderedMonoidPos (M: Type) (R: relation M) {op: Monoid_op M} {unit: Monoid_unit M} := { pompos_pom :> PreOrderedMonoid M R; pompos_pos: forall m, R Ƶ m; }. Section lemmas. Context `{PreOrderedMonoid M R}.W: Type
op: Monoid_op W
unit0: Monoid_unit W
H: Monoid W
A, B, C: Type
g: B -> C
f: W * A -> B
w: W(g ∘ f) ⦿ w = g ∘ f ⦿ wM: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M Rforall m n m' n' : M, R m m' -> R n n' -> R (m ● n) (m' ● n')M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M Rforall m n m' n' : M, R m m' -> R n n' -> R (m ● n) (m' ● n')M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
m, n, m', n': M
H0: R m m'
H1: R n n'R (m ● n) (m' ● n')M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
m, n, m', n': M
H0: R m m'
H1: R n n'R (m ● n) (m ● n')M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
m, n, m', n': M
H0: R m m'
H1: R n n'R (m ● n') (m' ● n')apply pom_mono_r; auto. Qed. Context `{! PreOrderedMonoidPos M R}.M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
m, n, m', n': M
H0: R m m'
H1: R n n'R (m ● n') (m' ● n')M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M Rforall m n : M, R m (m ● n)M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M Rforall m n : M, R m (m ● n)M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M R
m, n: MR m (m ● n)M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M R
m, n: MR (m ● Ƶ) (m ● n)apply pompos_pos. Qed.M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M R
m, n: MR Ƶ nM: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M Rforall m n : M, R m (n ● m)M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M Rforall m n : M, R m (n ● m)M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M R
m, n: MR m (n ● m)M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M R
m, n: MR (Ƶ ● m) (n ● m)apply pompos_pos. Qed. End lemmas. (** * Opposite Monoid *) (**********************************************************************) Section opposite_monoid. #[local] Instance OppositeMonoidOp `{Monoid_op M}: Monoid_op M := fun m1 m2 => m2 ● m1.M: Type
R: relation M
op: Monoid_op M
unit0: Monoid_unit M
H: PreOrderedMonoid M R
PreOrderedMonoidPos0: PreOrderedMonoidPos M R
m, n: MR Ƶ nM: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid MMonoid MM: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid MMonoid MM: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid M
x, y, z: M(x ● y) ● z = x ● (y ● z)M: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid M
x: Mx ● Ƶ = xM: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid M
x: MƵ ● x = xnow rewrite monoid_assoc.M: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid M
x, y, z: M(x ● y) ● z = x ● (y ● z)now rewrite monoid_id_r.M: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid M
x: Mx ● Ƶ = xnow rewrite monoid_id_l. Qed. End opposite_monoid. (** * Commutative Monoids *) (**********************************************************************) Class CommutativeMonoidOp {M: Type} (op: Monoid_op M) := {comm_mon_swap: forall (m1 m2: M), m1 ● m2 = m2 ● m1; }. Class CommutativeMonoid {M: Type} {op: Monoid_op M} {unit: Monoid_unit M} := { common_monoid: Monoid M; common_comm: CommutativeMonoidOp op; }. (** ** Opposite of a Commutative Monoid *) (**********************************************************************)M: Type
op: Monoid_op M
unit: Monoid_unit M
H: Monoid M
x: MƵ ● x = xM: Type
op: Monoid_op M
comm: CommutativeMonoidOp opCommutativeMonoidOp (Monoid_op_Opposite op)M: Type
op: Monoid_op M
comm: CommutativeMonoidOp opCommutativeMonoidOp (Monoid_op_Opposite op)M: Type
op: Monoid_op M
comm: CommutativeMonoidOp opforall m1 m2 : M, m1 ● m2 = m2 ● m1M: Type
op: Monoid_op M
comm: CommutativeMonoidOp op
m1, m2: Mm1 ● m2 = m2 ● m1M: Type
op: Monoid_op M
comm: CommutativeMonoidOp op
m1, m2: Mm1 ● m2 = m2 ● m1M: Type
op: Monoid_op M
comm: CommutativeMonoidOp op
m1, m2: Mm2 ● m1 = m1 ● m2reflexivity. Qed. (** * Idempotent Monoids *) (**********************************************************************) Class IdempotentMonoid {M: Type} {op: Monoid_op M} {unit: Monoid_unit M} := { idemmon_monoid: Monoid M; idemmon_idem: forall (m: M), m ● m = m; }. (** * Notations *) (**********************************************************************) Module Notations. Notation "'Ƶ'" := (monoid_unit _): tealeaves_scope. (* \Zbar *) Infix "●" := monoid_op (at level 60): tealeaves_scope. (* \CIRCLE *) Infix "⦿" := preincr (at level 30): tealeaves_scope. (* \circledbullet *) End Notations.M: Type
op: Monoid_op M
comm: CommutativeMonoidOp op
m1, m2: Mm1 ● m2 = m1 ● m2