dsalgo 0.2.6

A package for Datastructures and Algorithms.
Documentation
pub struct Additive;
pub struct Multiplicative;

pub trait Identity<S = Self, T = Additive> {
    fn identity() -> S;
}

pub trait BinaryOperation<S = Self, T = Additive> {
    fn operate(_: &S, _: &S) -> S;
}

pub trait Inverse<S = Self, T = Additive> {
    fn invert(_: &S) -> S;
}

pub trait Idempotent<S = Self, T = Additive> {}

pub trait Commutative<S = Self, T = Additive> {}

pub trait Semigroup<S = Self, T = Additive>: BinaryOperation<S, T> {}
impl<S, T, U: BinaryOperation<S, T>> Semigroup<S, T> for U {}

pub trait Monoid<S = Self, T = Additive>:
    Semigroup<S, T> + Identity<S, T>
{
}
impl<S, T, U: Semigroup<S, T> + Identity<S, T>> Monoid<S, T> for U {}

pub trait Group<S = Self, T = Additive>: Monoid<S, T> + Inverse<S, T> {}
impl<S, T, U: Monoid<S, T> + Inverse<S, T>> Group<S, T> for U {}

pub trait AbelianGroup<S = Self, T = Additive>:
    Group<S, T> + Commutative<S, T>
{
}
impl<S, T, U: Group<S, T> + Commutative<S, T>> AbelianGroup<S, T> for U {}

pub trait Semiring<S = Self, Add = Additive, Mul = Multiplicative>:
    Monoid<S, Add> + Monoid<S, Mul> + Commutative<S, Add>
{
}
impl<S, Add, Mul, U> Semiring<S, Add, Mul> for U where
    U: Monoid<S, Add> + Monoid<S, Mul> + Commutative<S, Add>
{
}

pub trait Ring<S = Self, Add = Additive, Mul = Multiplicative>:
    Semiring<S, Add, Mul> + Inverse<S, Add>
{
}
impl<S, Add, Mul, U> Ring<S, Add, Mul> for U where
    U: Semiring<S, Add, Mul> + Inverse<S, Add>
{
}

pub trait Default<S = Self, T = Additive> {
    fn default() -> S;
}

#[cfg(test)]
mod tests {
    // struct ExampleSemiring<S>(std::marker::PhantomData<S>);
    struct UsizeAddMul;

    impl super::Identity<usize, super::Additive> for UsizeAddMul {
        fn identity() -> usize { 0 }
    }

    impl super::Identity<usize, super::Multiplicative> for UsizeAddMul {
        fn identity() -> usize { 1 }
    }

    impl super::BinaryOperation<usize, super::Additive> for UsizeAddMul {
        fn operate(a: &usize, b: &usize) -> usize { a + b }
    }

    impl super::BinaryOperation<usize, super::Multiplicative> for UsizeAddMul {
        fn operate(a: &usize, b: &usize) -> usize { a * b }
    }

    impl super::Commutative<usize, super::Additive> for UsizeAddMul {}

    fn need_semiring<S, Add, Mul, U>()
    where
        U: super::Semiring<S, Add, Mul>,
        S: std::fmt::Debug + PartialEq,
    {
        let add_e = <U as super::Identity<S, Add>>::identity();
        let value_add =
            <U as super::BinaryOperation<S, Add>>::operate(&add_e, &add_e);
        assert_eq!(value_add, add_e);

        let mul_e = <U as super::Identity<S, Mul>>::identity();
        let value_mul =
            <U as super::BinaryOperation<S, Mul>>::operate(&mul_e, &mul_e);
        assert_eq!(value_mul, mul_e);
        eprintln!("{:?}", value_add);
    }

    #[test]
    fn test() {
        need_semiring::<
            usize,
            super::Additive,
            super::Multiplicative,
            UsizeAddMul,
        >();
    }
}