use crate::prelude::*;
pub trait Monoid {
#[must_use]
fn unit() -> Self;
#[must_use]
fn combine(self, other: Self) -> Self;
#[inline(always)]
#[must_use]
fn unify<F: Fold<Item = Self>>(f: F) -> Self
where
Self: Sized,
F::IntoIter: DoubleEndedIterator,
{
f.foldr(combine, unit())
}
}
#[inline(always)]
#[must_use]
pub fn combine<M: Monoid>(a: M, b: M) -> M {
M::combine(a, b)
}
#[inline(always)]
#[must_use]
pub fn unit<M: Monoid>() -> M {
M::unit()
}
#[inline(always)]
#[must_use]
pub fn unify<M: Monoid, F: Fold<Item = M>>(f: F) -> M
where
F::IntoIter: DoubleEndedIterator,
{
M::unify(f)
}