1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
use crate::{
    binary_operation::BinaryOperationId,
    commutative_monoid::CommutativeMonoid,
    distributive_property::DistributiveProperty,
    magma::Magma,
    monoid::Monoid,
    zero_element::ZeroElement,
};

pub trait Semiring<Add, Mul>
where
    Add: BinaryOperationId,
    Mul: BinaryOperationId,
{
    type S;
    fn add(l: Self::S, r: Self::S) -> Self::S;
    fn mul(l: Self::S, r: Self::S) -> Self::S;
    fn zero() -> Self::S;
    fn one() -> Self::S;
}

impl<S, Add, Mul, T> Semiring<Add, Mul> for T
where
    T: CommutativeMonoid<Add, S = S>
        + Monoid<Mul, S = S>
        + DistributiveProperty<Add, Mul>
        + ZeroElement<Add, Mul>,
    Add: BinaryOperationId,
    Mul: BinaryOperationId,
{
    type S = S;

    fn add(l: Self::S, r: Self::S) -> Self::S {
        <T as Magma<Add>>::operate(l, r)
    }

    fn mul(l: Self::S, r: Self::S) -> Self::S {
        <T as Magma<Mul>>::operate(l, r)
    }

    fn zero() -> Self::S { <T as Monoid<Add>>::identity() }

    fn one() -> Self::S { <T as Monoid<Mul>>::identity() }
}