1use alloc::boxed::Box;
2
3pub trait Morphism {
4 type Domain: Clone;
5 type Codomain: Clone;
6
7 fn apply(&self, x: &Self::Domain) -> Self::Codomain;
8}
9
10pub trait Composable<M>: Morphism
11where
12 M: Morphism<Codomain = Self::Domain>,
13{
14 type Composed: Morphism<Domain = M::Domain, Codomain = Self::Codomain>;
15 fn compose(self, other: M) -> Self::Composed;
16}
17
18pub trait Invertible: Morphism {
19 type Inverse: Morphism<Domain = Self::Codomain, Codomain = Self::Domain>;
20 fn inverse(self) -> Self::Inverse;
21}
22
23pub struct MapMorphism<A, B> {
24 f: Box<dyn Fn(&A) -> B + Send + Sync>,
25}
26
27impl<A: Clone, B: Clone> MapMorphism<A, B> {
28 pub fn new<F>(f: F) -> Self
29 where
30 F: Fn(&A) -> B + Send + Sync + 'static,
31 {
32 Self { f: Box::new(f) }
33 }
34}
35
36impl<A: Clone, B: Clone> Morphism for MapMorphism<A, B> {
37 type Domain = A;
38 type Codomain = B;
39
40 fn apply(&self, x: &A) -> B {
41 (self.f)(x)
42 }
43}
44
45pub struct ComposedMorphism<F, G> {
46 outer: F,
47 inner: G,
48}
49
50impl<F, G> Morphism for ComposedMorphism<F, G>
51where
52 F: Morphism,
53 G: Morphism<Codomain = F::Domain>,
54{
55 type Domain = G::Domain;
56 type Codomain = F::Codomain;
57
58 fn apply(&self, x: &Self::Domain) -> Self::Codomain {
59 let intermediate = self.inner.apply(x);
60 self.outer.apply(&intermediate)
61 }
62}
63
64impl<F, G> Composable<G> for F
65where
66 F: Morphism,
67 G: Morphism<Codomain = F::Domain>,
68{
69 type Composed = ComposedMorphism<F, G>;
70
71 fn compose(self, other: G) -> Self::Composed {
72 ComposedMorphism {
73 outer: self,
74 inner: other,
75 }
76 }
77}
78
79pub struct IdentityMorphism<A> {
80 _marker: core::marker::PhantomData<A>,
81}
82
83impl<A> IdentityMorphism<A> {
84 pub fn new() -> Self {
85 Self {
86 _marker: core::marker::PhantomData,
87 }
88 }
89}
90
91impl<A> Default for IdentityMorphism<A> {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97impl<A: Clone> Morphism for IdentityMorphism<A> {
98 type Domain = A;
99 type Codomain = A;
100
101 fn apply(&self, x: &A) -> A {
102 x.clone()
103 }
104}
105
106impl<A: Clone> Invertible for IdentityMorphism<A> {
107 type Inverse = IdentityMorphism<A>;
108
109 fn inverse(self) -> Self::Inverse {
110 Self::new()
111 }
112}