Skip to main content

karpal_higher/
ffunctor.rs

1// Copyright (C) 2026 Industrial Algebra
2// SPDX-License-Identifier: Apache-2.0
3
4//! Higher functors and monads at the 2-categorical level.
5//!
6//! - `FFunctor`: a functor between 2-categories that preserves 2-morphisms
7//! - `FMonad`: a monad in the endofunctor 2-category `Endo(C)`
8
9use crate::two_category::TwoCategory;
10
11/// A functor between two 2-categories that preserves the 2-categorical structure.
12///
13/// `FFunctor` maps objects, 1-morphisms, and 2-morphisms from `C1` to `C2`
14/// while preserving identity and composition.
15pub trait FFunctor<C1: TwoCategory, C2: TwoCategory> {
16    /// Map a 1-morphism from C1 to C2.
17    fn map_morphism<A: 'static, B: 'static>(f: C1::Morphism<A, B>) -> C2::Morphism<A, B>;
18
19    /// Map a 2-morphism from C1 to C2.
20    fn map_two_morphism(alpha: C1::TwoMorphism) -> C2::TwoMorphism;
21}
22
23// ---------------------------------------------------------------------------
24// Identity FFunctor
25// ---------------------------------------------------------------------------
26
27/// The identity functor on a 2-category C.
28pub struct IdentityFFunctor<C: TwoCategory>(core::marker::PhantomData<C>);
29
30impl<C: TwoCategory> FFunctor<C, C> for IdentityFFunctor<C> {
31    fn map_morphism<A: 'static, B: 'static>(f: C::Morphism<A, B>) -> C::Morphism<A, B> {
32        f
33    }
34
35    fn map_two_morphism(alpha: C::TwoMorphism) -> C::TwoMorphism {
36        alpha
37    }
38}
39
40// ---------------------------------------------------------------------------
41// FMonad
42// ---------------------------------------------------------------------------
43
44/// A monad in the 2-category of endofunctors `Endo(C)`.
45///
46/// An `FMonad` on a 2-category `C` is an endofunctor `T` together with
47/// 2-morphisms `η: Id ⇒ T` (unit) and `μ: T ∘ T ⇒ T` (multiplication)
48/// satisfying the monad laws.
49pub trait FMonad<C: TwoCategory>: FFunctor<C, C> {
50    /// Unit: `η: Id ⇒ T`
51    fn unit<A: 'static>() -> C::TwoMorphism;
52
53    /// Multiplication: `μ: T ∘ T ⇒ T`
54    fn multiply<A: 'static>() -> C::TwoMorphism;
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    #[cfg(any(feature = "std", feature = "alloc"))]
61    use crate::two_category::Cat;
62
63    #[test]
64    fn identity_ffunctor_preserves_morphism() {
65        struct Marker;
66        impl TwoCategory for Marker {
67            type Morphism<A, B> = ();
68            type TwoMorphism = ();
69            fn id1<A: 'static>() -> Self::Morphism<A, A> {}
70            fn compose1<A: 'static, B: 'static, C: 'static>(
71                _: Self::Morphism<A, B>,
72                _: Self::Morphism<B, C>,
73            ) -> Self::Morphism<A, C> {
74            }
75            fn id2() -> Self::TwoMorphism {}
76            fn compose2_vertical(_: Self::TwoMorphism, _: Self::TwoMorphism) -> Self::TwoMorphism {}
77        }
78        let _unit: () = IdentityFFunctor::<Marker>::map_morphism::<(), ()>(());
79    }
80
81    #[test]
82    fn id_ffunctor_preserves_two_morphism() {
83        struct Marker;
84        impl TwoCategory for Marker {
85            type Morphism<A, B> = ();
86            type TwoMorphism = ();
87            fn id1<A: 'static>() -> Self::Morphism<A, A> {}
88            fn compose1<A: 'static, B: 'static, C: 'static>(
89                _: Self::Morphism<A, B>,
90                _: Self::Morphism<B, C>,
91            ) -> Self::Morphism<A, C> {
92            }
93            fn id2() -> Self::TwoMorphism {}
94            fn compose2_vertical(_: Self::TwoMorphism, _: Self::TwoMorphism) -> Self::TwoMorphism {}
95        }
96        let _unit: () = IdentityFFunctor::<Marker>::map_two_morphism(());
97    }
98}