pub trait BinaryOperationIdentifier {}
pub trait BinaryOperation<F: ?Sized, T: ?Sized, I: BinaryOperationIdentifier> {
fn operate(self, operator: F) -> T;
}
pub trait AssociativeProperty<I: BinaryOperationIdentifier>:
BinaryOperation<Self, Self, I>
{
fn assert_associative(first: Self, second: Self, third: Self)
where
Self: Copy + PartialEq + Debug,
{
assert_eq!(
first.operate(second).operate(third),
first.operate(second.operate(third))
);
}
}
pub trait Idempotence<I: BinaryOperationIdentifier>:
BinaryOperation<Self, Self, I>
{
fn assert_idempotent(self)
where
Self: Copy + PartialEq + Debug,
{
assert_eq!(self.operate(self), self);
}
}
pub trait CommutativeProperty<T: Sized, I: BinaryOperationIdentifier>:
BinaryOperation<Self, T, I> + Sized
{
fn assert_commutative(self, operator: Self)
where
Self: Copy,
T: PartialEq + Debug,
{
assert_eq!(
self.operate(operator),
operator.operate(self)
);
}
}
pub trait IdentityElement<I: BinaryOperationIdentifier>:
BinaryOperation<Self, Self, I>
{
fn identity() -> Self;
}
use std::fmt::Debug;
pub trait InverseElement<I: BinaryOperationIdentifier>:
IdentityElement<I>
{
fn invert(self) -> Self;
}
pub trait Magma<I: BinaryOperationIdentifier>:
BinaryOperation<Self, Self, I>
{
}
impl<I: BinaryOperationIdentifier, S: BinaryOperation<Self, Self, I>> Magma<I>
for S
{
}
pub trait Semigroup<I: BinaryOperationIdentifier>:
Magma<I> + AssociativeProperty<I>
{
}
impl<I: BinaryOperationIdentifier, S: Magma<I> + AssociativeProperty<I>>
Semigroup<I> for S
{
}
pub trait Monoid<I: BinaryOperationIdentifier>:
Semigroup<I> + IdentityElement<I>
{
}
impl<I: BinaryOperationIdentifier, S: Semigroup<I> + IdentityElement<I>>
Monoid<I> for S
{
}
pub trait CommutativeMonoid<I: BinaryOperationIdentifier>:
Monoid<I> + CommutativeProperty<Self, I> + Sized
{
}
impl<I, S> CommutativeMonoid<I> for S
where
I: BinaryOperationIdentifier,
S: Monoid<I> + CommutativeProperty<Self, I>,
{
}
pub trait Group<I: BinaryOperationIdentifier>:
Monoid<I> + InverseElement<I>
{
}
impl<I: BinaryOperationIdentifier, S: Monoid<I> + InverseElement<I>> Group<I>
for S
{
}
pub trait AbelianGroup<I: BinaryOperationIdentifier>:
Group<I> + CommutativeProperty<Self, I>
{
}
impl<I: BinaryOperationIdentifier, S: Group<I> + CommutativeProperty<Self, I>>
AbelianGroup<I> for S
{
}
pub trait Semiring<I, J>: CommutativeMonoid<I> + Monoid<J>
where
I: BinaryOperationIdentifier,
J: BinaryOperationIdentifier,
{
}
impl<I, J, S> Semiring<I, J> for S
where
I: BinaryOperationIdentifier,
J: BinaryOperationIdentifier,
S: CommutativeMonoid<I> + Monoid<J>,
{
}
pub trait Ring<I, J>: Semiring<I, J> + InverseElement<I>
where
I: BinaryOperationIdentifier,
J: BinaryOperationIdentifier,
{
}
impl<I, J, S: Semiring<I, J> + InverseElement<I>> Ring<I, J> for S
where
I: BinaryOperationIdentifier,
J: BinaryOperationIdentifier,
{
}
pub trait Default<I: BinaryOperationIdentifier>:
BinaryOperation<Self, Self, I> + Sized
{
fn default() -> Self;
}
pub struct Additive;
impl crate::group_theory::BinaryOperationIdentifier for Additive {}
pub struct Multiplicative;
impl crate::group_theory::BinaryOperationIdentifier for Multiplicative {}
pub trait AdditiveGroup: AbelianGroup<Additive> {}
impl<S: AbelianGroup<Additive>> AdditiveGroup for S {}
#[cfg(test)]
mod tests {
fn need_semiring<
S,
I: super::BinaryOperationIdentifier,
J: super::BinaryOperationIdentifier,
>()
where
S: super::Semiring<I, J> + std::fmt::Debug + PartialEq + Copy,
{
let add_e = <S as super::IdentityElement<I>>::identity();
let value_add =
<S as super::BinaryOperation<_, _, I>>::operate(add_e, add_e);
assert_eq!(value_add, add_e);
let mul_e = <S as super::IdentityElement<J>>::identity();
let value_mul =
<S as super::BinaryOperation<_, _, J>>::operate(mul_e, mul_e);
assert_eq!(value_mul, mul_e);
eprintln!("{:?}", value_add);
}
#[test]
fn test() {
need_semiring::<usize, super::Additive, super::Multiplicative>();
}
}