use general::{Semigroup, Op, Additive, Identity, Multiplicative};
use cmp::ApproxEq;
pub trait Monoid<O: Op>
: Semigroup<O>
+ Identity<O>
{
fn prop_operating_identity_element_is_noop(a: Self) -> bool
where Self: ApproxEq {
let a = || a.clone();
(a().operate(Identity::id())).approx_eq(&a()) &&
(Self::id().operate(a())).approx_eq(&a())
}
}
impl_marker!(Monoid<Additive>; u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
impl_marker!(Monoid<Multiplicative>; u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
#[cfg(test)]
mod tests {
macro_rules! check_int {
($($T:ident),* $(,)*) => {
$(mod $T {
use ops::{Additive, Multiplicative};
use general::Monoid;
#[quickcheck]
fn prop_zero_is_noop(args: $T) -> bool {
Monoid::<Additive>::prop_operating_identity_element_is_noop(args)
}
#[quickcheck]
fn prop_mul_unit_is_noop(args: $T) -> bool {
Monoid::<Multiplicative>::prop_operating_identity_element_is_noop(args)
}
})+
}
}
check_int!(u8, u16, u32, u64, i8, i16, i32, i64);
}