amonoid 0.1.2

A general-purpose monoid library
Documentation
//! Operational types that allow the use of the monoid operation as an operator.

use std::iter::{Product, Sum};
use std::ops::{Add, Mul};

use crate::Monoid;

/// Write a monoid additively.
///
/// This is usually done if the operation is commutative, but that isn't required here.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Additive<M>(pub M);

impl<M: Monoid> Add for Additive<M> {
	type Output = Self;

	fn add(self, rhs: Self) -> Self::Output {
		Self(self.0.combine(rhs.0))
	}
}
#[cfg(feature = "num-traits")]
impl<M: Monoid + Eq> num_traits::Zero for Additive<M> {
	fn zero() -> Self {
		Self(M::ident())
	}

	fn is_zero(&self) -> bool {
		self.0 == M::ident()
	}
}

impl<M: Monoid> Sum<M> for Additive<M> {
	fn sum<I: Iterator<Item = M>>(iter: I) -> Self {
		Self(M::combine_iter(iter))
	}
}
impl<M: Monoid> Sum<Self> for Additive<M> {
	fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
		iter.map(|a| a.0).sum()
	}
}

/// Write a monoid multiplicatively.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Multiplicative<M>(pub M);

impl<M: Monoid> Mul for Multiplicative<M> {
	type Output = Self;

	fn mul(self, rhs: Self) -> Self::Output {
		Self(self.0.combine(rhs.0))
	}
}
#[cfg(feature = "num-traits")]
impl<M: Monoid + Eq> num_traits::One for Multiplicative<M> {
	fn one() -> Self {
		Self(M::ident())
	}

	fn is_one(&self) -> bool {
		self.0 == M::ident()
	}
}

impl<M: Monoid> Product<M> for Multiplicative<M> {
	fn product<I: Iterator<Item = M>>(iter: I) -> Self {
		Self(M::combine_iter(iter))
	}
}
impl<M: Monoid> Product<Self> for Multiplicative<M> {
	fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
		iter.map(|a| a.0).product()
	}
}