#![doc(include = "../../doc/references.md")]
use crate::semigroup::*;
pub trait Monoid: Semigroup {
fn id() -> Self;
fn is_id(&self) -> bool {
*self == Self::id()
}
}
pub trait MonoidLaws: Monoid {
fn left_identity(&self) -> bool {
Self::id().op(self) == *self
}
fn right_identity(&self) -> bool {
self.op(&Self::id()) == *self
}
fn identity(&self) -> bool {
self.left_identity() && self.right_identity()
}
}
impl<S: Monoid> MonoidLaws for S {}
impl Monoid for () {
fn id() -> Self {}
}
impl<T: Monoid> Monoid for (T,) {
fn id() -> Self {
(T::id(), )
}
}
impl<A: Monoid, B: Monoid> Monoid for (A, B) {
fn id() -> Self {
(A::id(), B::id())
}
}
impl<A: Monoid, B: Monoid, C: Monoid> Monoid for (A, B, C) {
fn id() -> Self {
(A::id(), B::id(), C::id())
}
}
macro_rules! array_monoid {
($size:expr) => {
impl<T: Copy + Monoid> Monoid for [T; $size] {
fn id() -> Self {
[T::id(); $size]
}
}
};
($size:expr, $($others:expr),+) => {
array_monoid! {$size}
array_monoid! {$($others),+}
};
}
array_monoid! {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}