alice-math 0.1.0

A topology and algebra library from first principles
Documentation
use alloc::boxed::Box;

pub trait Morphism {
    type Domain: Clone;
    type Codomain: Clone;

    fn apply(&self, x: &Self::Domain) -> Self::Codomain;
}

pub trait Composable<M>: Morphism
where
    M: Morphism<Codomain = Self::Domain>,
{
    type Composed: Morphism<Domain = M::Domain, Codomain = Self::Codomain>;
    fn compose(self, other: M) -> Self::Composed;
}

pub trait Invertible: Morphism {
    type Inverse: Morphism<Domain = Self::Codomain, Codomain = Self::Domain>;
    fn inverse(self) -> Self::Inverse;
}

pub struct MapMorphism<A, B> {
    f: Box<dyn Fn(&A) -> B + Send + Sync>,
}

impl<A: Clone, B: Clone> MapMorphism<A, B> {
    pub fn new<F>(f: F) -> Self
    where
        F: Fn(&A) -> B + Send + Sync + 'static,
    {
        Self { f: Box::new(f) }
    }
}

impl<A: Clone, B: Clone> Morphism for MapMorphism<A, B> {
    type Domain = A;
    type Codomain = B;

    fn apply(&self, x: &A) -> B {
        (self.f)(x)
    }
}

pub struct ComposedMorphism<F, G> {
    outer: F,
    inner: G,
}

impl<F, G> Morphism for ComposedMorphism<F, G>
where
    F: Morphism,
    G: Morphism<Codomain = F::Domain>,
{
    type Domain = G::Domain;
    type Codomain = F::Codomain;

    fn apply(&self, x: &Self::Domain) -> Self::Codomain {
        let intermediate = self.inner.apply(x);
        self.outer.apply(&intermediate)
    }
}

impl<F, G> Composable<G> for F
where
    F: Morphism,
    G: Morphism<Codomain = F::Domain>,
{
    type Composed = ComposedMorphism<F, G>;

    fn compose(self, other: G) -> Self::Composed {
        ComposedMorphism {
            outer: self,
            inner: other,
        }
    }
}

pub struct IdentityMorphism<A> {
    _marker: core::marker::PhantomData<A>,
}

impl<A> IdentityMorphism<A> {
    pub fn new() -> Self {
        Self {
            _marker: core::marker::PhantomData,
        }
    }
}

impl<A> Default for IdentityMorphism<A> {
    fn default() -> Self {
        Self::new()
    }
}

impl<A: Clone> Morphism for IdentityMorphism<A> {
    type Domain = A;
    type Codomain = A;

    fn apply(&self, x: &A) -> A {
        x.clone()
    }
}

impl<A: Clone> Invertible for IdentityMorphism<A> {
    type Inverse = IdentityMorphism<A>;

    fn inverse(self) -> Self::Inverse {
        Self::new()
    }
}