pub trait TwoCategory {
type Morphism<A, B>;
type TwoMorphism;
fn id1<A: 'static>() -> Self::Morphism<A, A>;
fn compose1<A: 'static, B: 'static, C: 'static>(
f: Self::Morphism<A, B>,
g: Self::Morphism<B, C>,
) -> Self::Morphism<A, C>;
fn id2() -> Self::TwoMorphism;
fn compose2_vertical(alpha: Self::TwoMorphism, beta: Self::TwoMorphism) -> Self::TwoMorphism;
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct Cat;
#[cfg(any(feature = "std", feature = "alloc"))]
impl TwoCategory for Cat {
type Morphism<A, B> = Box<dyn Fn(A) -> B>;
type TwoMorphism = ();
fn id1<A: 'static>() -> Self::Morphism<A, A> {
Box::new(|a| a)
}
fn compose1<A: 'static, B: 'static, C: 'static>(
f: Self::Morphism<A, B>,
g: Self::Morphism<B, C>,
) -> Self::Morphism<A, C> {
Box::new(move |a| g(f(a)))
}
fn id2() -> Self::TwoMorphism {}
fn compose2_vertical(_alpha: Self::TwoMorphism, _beta: Self::TwoMorphism) -> Self::TwoMorphism {
}
}
#[cfg(all(test, any(feature = "std", feature = "alloc")))]
mod tests {
use super::*;
#[test]
fn cat_id1_is_identity_function() {
let id: Box<dyn Fn(i32) -> i32> = Cat::id1();
assert_eq!(id(42), 42);
}
#[test]
fn cat_compose1_chains_functions() {
let f: Box<dyn Fn(i32) -> i32> = Box::new(|x| x + 1);
let g: Box<dyn Fn(i32) -> i32> = Box::new(|x| x * 2);
let gf = Cat::compose1(f, g);
assert_eq!(gf(5), 12); }
#[test]
fn cat_compose2_vertical_is_total() {
let alpha = Cat::id2();
let beta = Cat::id2();
let _gamma = Cat::compose2_vertical(alpha, beta);
}
}