use crate::algaeset::AlgaeSet;
use crate::mapping::{BinaryOperation, PropertyError, PropertyType};
pub trait Magmoid<T: Copy + PartialEq> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T>;
fn with(&mut self, left: T, right: T) -> Result<T, PropertyError> {
self.binop().with(left, right)
}
}
pub struct Magma<'a, T> {
aset: AlgaeSet<T>,
binop: &'a mut dyn BinaryOperation<T>,
}
impl<'a, T> Magma<'a, T> {
pub fn new(aset: AlgaeSet<T>, binop: &'a mut dyn BinaryOperation<T>) -> Self {
Self { aset, binop }
}
}
impl<'a, T: Copy + PartialEq> Magmoid<T> for Magma<'a, T> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T> {
self.binop
}
}
pub struct UnitalMagma<'a, T> {
aset: AlgaeSet<T>,
binop: &'a mut dyn BinaryOperation<T>,
identity: T,
}
impl<'a, T: Copy + PartialEq> UnitalMagma<'a, T> {
pub fn new(aset: AlgaeSet<T>, binop: &'a mut dyn BinaryOperation<T>, identity: T) -> Self {
assert!(binop.is(PropertyType::WithIdentity(identity)));
Self {
aset,
binop,
identity,
}
}
}
impl<'a, T: Copy + PartialEq> Magmoid<T> for UnitalMagma<'a, T> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T> {
self.binop
}
}
impl<'a, T> Into<Magma<'a, T>> for UnitalMagma<'a, T> {
fn into(self) -> Magma<'a, T> {
Magma::new(self.aset, self.binop)
}
}
pub struct Groupoid<'a, T> {
aset: AlgaeSet<T>,
binop: &'a mut dyn BinaryOperation<T>,
}
impl<'a, T: Copy + PartialEq> Groupoid<'a, T> {
pub fn new(aset: AlgaeSet<T>, binop: &'a mut dyn BinaryOperation<T>) -> Self {
assert!(binop.is(PropertyType::Associative));
Self { aset, binop }
}
}
impl<'a, T: Copy + PartialEq> Magmoid<T> for Groupoid<'a, T> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T> {
self.binop
}
}
impl<'a, T> Into<Magma<'a, T>> for Groupoid<'a, T> {
fn into(self) -> Magma<'a, T> {
Magma::new(self.aset, self.binop)
}
}
pub struct Quasigroup<'a, T> {
aset: AlgaeSet<T>,
binop: &'a mut dyn BinaryOperation<T>,
}
impl<'a, T: Copy + PartialEq> Quasigroup<'a, T> {
pub fn new(aset: AlgaeSet<T>, binop: &'a mut dyn BinaryOperation<T>) -> Self {
assert!(binop.is(PropertyType::Cancellative));
Self { aset, binop }
}
}
impl<'a, T: Copy + PartialEq> Magmoid<T> for Quasigroup<'a, T> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T> {
self.binop
}
}
impl<'a, T> Into<Magma<'a, T>> for Quasigroup<'a, T> {
fn into(self) -> Magma<'a, T> {
Magma::new(self.aset, self.binop)
}
}
pub struct Monoid<'a, T> {
aset: AlgaeSet<T>,
binop: &'a mut dyn BinaryOperation<T>,
identity: T,
}
impl<'a, T: Copy + PartialEq> Monoid<'a, T> {
pub fn new(aset: AlgaeSet<T>, binop: &'a mut dyn BinaryOperation<T>, identity: T) -> Self {
assert!(binop.is(PropertyType::Associative));
assert!(binop.is(PropertyType::WithIdentity(identity)));
Self {
aset,
binop,
identity,
}
}
}
impl<'a, T: Copy + PartialEq> Magmoid<T> for Monoid<'a, T> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T> {
self.binop
}
}
impl<'a, T> Into<Magma<'a, T>> for Monoid<'a, T> {
fn into(self) -> Magma<'a, T> {
Magma::new(self.aset, self.binop)
}
}
impl<'a, T: Copy + PartialEq> Into<Groupoid<'a, T>> for Monoid<'a, T> {
fn into(self) -> Groupoid<'a, T> {
Groupoid::new(self.aset, self.binop)
}
}
impl<'a, T: Copy + PartialEq> Into<UnitalMagma<'a, T>> for Monoid<'a, T> {
fn into(self) -> UnitalMagma<'a, T> {
UnitalMagma::new(self.aset, self.binop, self.identity)
}
}
pub struct Loop<'a, T> {
aset: AlgaeSet<T>,
binop: &'a mut dyn BinaryOperation<T>,
identity: T,
}
impl<'a, T: Copy + PartialEq> Loop<'a, T> {
pub fn new(aset: AlgaeSet<T>, binop: &'a mut dyn BinaryOperation<T>, identity: T) -> Self {
assert!(binop.is(PropertyType::Cancellative));
assert!(binop.is(PropertyType::WithIdentity(identity)));
Self {
aset,
binop,
identity,
}
}
}
impl<'a, T: Copy + PartialEq> Magmoid<T> for Loop<'a, T> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T> {
self.binop
}
}
impl<'a, T> Into<Magma<'a, T>> for Loop<'a, T> {
fn into(self) -> Magma<'a, T> {
Magma::new(self.aset, self.binop)
}
}
impl<'a, T: Copy + PartialEq> Into<UnitalMagma<'a, T>> for Loop<'a, T> {
fn into(self) -> UnitalMagma<'a, T> {
UnitalMagma::new(self.aset, self.binop, self.identity)
}
}
impl<'a, T: Copy + PartialEq> Into<Quasigroup<'a, T>> for Loop<'a, T> {
fn into(self) -> Quasigroup<'a, T> {
Quasigroup::new(self.aset, self.binop)
}
}