1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
use super::arrow::Arrow;
use super::entity::Concept;
/// A category: a collection of objects (concepts) and morphisms (relationships)
/// where composition and identity laws hold.
///
/// # Laws
///
/// A valid category must satisfy:
/// - **Identity**: For every object A, there exists an identity morphism id_A
/// such that compose(id_A, f) == f and compose(f, id_A) == f for all f.
/// - **Associativity**: compose(compose(f, g), h) == compose(f, compose(g, h))
/// - **Closure**: If f: A → B and g: B → C, then compose(f, g): A → C exists.
///
/// Use [`crate::category::laws`] to verify these laws via property-based testing.
pub trait Category {
type Object: Concept;
type Morphism: Arrow<Object = Self::Object>;
/// The identity morphism for an object (id_A: A → A).
fn identity(obj: &Self::Object) -> Self::Morphism;
/// Compose two morphisms: given f: A → B and g: B → C, produce g∘f: A → C.
///
/// Returns `None` if the morphisms don't compose (f.target != g.source).
fn compose(f: &Self::Morphism, g: &Self::Morphism) -> Option<Self::Morphism>;
/// All morphisms in this category.
fn morphisms() -> Vec<Self::Morphism>;
/// All morphisms originating from the given object.
fn morphisms_from(obj: &Self::Object) -> Vec<Self::Morphism> {
Self::morphisms()
.into_iter()
.filter(|m| &m.source() == obj)
.collect()
}
/// All morphisms targeting the given object.
fn morphisms_to(obj: &Self::Object) -> Vec<Self::Morphism> {
Self::morphisms()
.into_iter()
.filter(|m| &m.target() == obj)
.collect()
}
}