pub trait Semiring: Clone + PartialEq + core::fmt::Debug {
fn zero() -> Self;
fn one() -> Self;
fn add(&self, other: &Self) -> Self;
fn mul(&self, other: &Self) -> Self;
fn is_zero(&self) -> bool {
*self == Self::zero()
}
fn star(&self) -> Option<Self> {
None
}
}
#[cfg(test)]
pub(crate) mod laws {
use super::Semiring;
pub(crate) fn assert_semiring_laws<S: Semiring>(samples: &[S]) {
let zero = S::zero();
let one = S::one();
for a in samples {
assert_eq!(zero.add(a), *a, "zero + a == a");
assert_eq!(a.add(&zero), *a, "a + zero == a");
assert_eq!(one.mul(a), *a, "one * a == a");
assert_eq!(a.mul(&one), *a, "a * one == a");
assert_eq!(zero.mul(a), zero, "zero * a == zero");
assert_eq!(a.mul(&zero), zero, "a * zero == zero");
assert_eq!(a.is_zero(), *a == zero, "is_zero agrees with == zero");
}
for a in samples {
for b in samples {
assert_eq!(a.add(b), b.add(a), "add is commutative");
for c in samples {
assert_eq!(a.add(b).add(c), a.add(&b.add(c)), "add is associative");
assert_eq!(a.mul(b).mul(c), a.mul(&b.mul(c)), "mul is associative");
assert_eq!(
a.mul(&b.add(c)),
a.mul(b).add(&a.mul(c)),
"left distributive"
);
assert_eq!(
a.add(b).mul(c),
a.mul(c).add(&b.mul(c)),
"right distributive"
);
}
}
}
}
}