use crate::algaeset::AlgaeSet;
use crate::mapping::{binop_has_invertible_identity, binop_is_invertible};
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> From<UnitalMagma<'a, T>> for Magma<'a, T> {
fn from(magma: UnitalMagma<'a, T>) -> Magma<'a, T> {
Magma::new(magma.aset, magma.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> From<Groupoid<'a, T>> for Magma<'a, T> {
fn from(groupoid: Groupoid<'a, T>) -> Magma<'a, T> {
Magma::new(groupoid.aset, groupoid.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> From<Quasigroup<'a, T>> for Magma<'a, T> {
fn from(quasi: Quasigroup<'a, T>) -> Magma<'a, T> {
Magma::new(quasi.aset, quasi.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: Copy + PartialEq> From<Monoid<'a, T>> for Magma<'a, T> {
fn from(monoid: Monoid<'a, T>) -> Magma<'a, T> {
Magma::new(monoid.aset, monoid.binop)
}
}
impl<'a, T: Copy + PartialEq> From<Monoid<'a, T>> for Groupoid<'a, T> {
fn from(monoid: Monoid<'a, T>) -> Groupoid<'a, T> {
Groupoid::new(monoid.aset, monoid.binop)
}
}
impl<'a, T: Copy + PartialEq> From<Monoid<'a, T>> for UnitalMagma<'a, T> {
fn from(monoid: Monoid<'a, T>) -> UnitalMagma<'a ,T> {
UnitalMagma::new(monoid.aset, monoid.binop, monoid.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: Copy + PartialEq> From<Loop<'a, T>> for Magma<'a, T> {
fn from(loop_: Loop<'a, T>) -> Magma<'a, T> {
Magma::new(loop_.aset, loop_.binop)
}
}
impl<'a, T: Copy + PartialEq> From<Loop<'a, T>> for UnitalMagma<'a, T> {
fn from(loop_: Loop<'a, T>) -> UnitalMagma<'a, T> {
UnitalMagma::new(loop_.aset, loop_.binop, loop_.identity)
}
}
impl<'a, T: Copy + PartialEq> From<Loop<'a, T>> for Quasigroup<'a, T> {
fn from(loop_: Loop<'a, T>) -> Quasigroup<'a, T> {
Quasigroup::new(loop_.aset, loop_.binop)
}
}
pub struct Group<'a, T> {
aset: AlgaeSet<T>,
binop: &'a mut dyn BinaryOperation<T>,
identity: T,
}
impl<'a, T: Copy + PartialEq> Group<'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)));
assert!(binop_is_invertible(binop));
assert!(binop_has_invertible_identity(binop, identity));
Self {
aset,
binop,
identity,
}
}
}
impl<'a, T: Copy + PartialEq> Magmoid<T> for Group<'a, T> {
fn binop(&mut self) -> &mut dyn BinaryOperation<T> {
self.binop
}
}
impl<'a, T> From<Group<'a, T>> for Magma<'a, T> {
fn from(group: Group<'a, T>) -> Magma<'a, T> {
Magma::new(group.aset, group.binop)
}
}
impl<'a, T: Copy + PartialEq> From<Group<'a, T>> for UnitalMagma<'a, T> {
fn from(group: Group<'a, T>) -> UnitalMagma<'a, T> {
UnitalMagma::new(group.aset, group.binop, group.identity)
}
}
impl<'a, T: Copy + PartialEq> From<Group<'a, T>> for Quasigroup<'a, T> {
fn from(group: Group<'a, T>) -> Quasigroup<'a, T> {
Quasigroup::new(group.aset, group.binop)
}
}