catlog/dbl/discrete/
theory.rs1use std::ops::Range;
4
5use derive_more::From;
6use ref_cast::RefCast;
7
8use crate::dbl::{category::*, tree::DblTree};
9use crate::one::{Path, category::*, fp_category::UstrFpCategory};
10use crate::validate::Validate;
11
12#[derive(From, RefCast, Debug)]
22#[repr(transparent)]
23pub struct DiscreteDblTheory<Cat: FgCategory>(Cat);
24
25pub type UstrDiscreteDblTheory = DiscreteDblTheory<UstrFpCategory>;
27
28impl<Cat: FgCategory> DiscreteDblTheory<Cat> {
29 pub fn category(&self) -> &Cat {
31 &self.0
32 }
33}
34
35impl<C: FgCategory> VDblCategory for DiscreteDblTheory<C>
36where
37 C::Ob: Clone,
38 C::Mor: Clone,
39{
40 type Ob = C::Ob;
41 type Arr = C::Ob;
42 type Pro = C::Mor;
43 type Cell = Path<C::Ob, C::Mor>;
44
45 fn has_ob(&self, ob: &Self::Ob) -> bool {
46 self.0.has_ob(ob)
47 }
48 fn has_arrow(&self, arr: &Self::Arr) -> bool {
49 self.0.has_ob(arr)
50 }
51 fn has_proarrow(&self, pro: &Self::Pro) -> bool {
52 self.0.has_mor(pro)
53 }
54 fn has_cell(&self, path: &Self::Cell) -> bool {
55 path.contained_in(UnderlyingGraph::ref_cast(&self.0))
56 }
57
58 fn dom(&self, f: &Self::Arr) -> Self::Ob {
59 f.clone()
60 }
61 fn cod(&self, f: &Self::Arr) -> Self::Ob {
62 f.clone()
63 }
64 fn src(&self, m: &Self::Pro) -> Self::Ob {
65 self.0.dom(m)
66 }
67 fn tgt(&self, m: &Self::Pro) -> Self::Ob {
68 self.0.cod(m)
69 }
70
71 fn cell_dom(&self, path: &Self::Cell) -> Path<Self::Ob, Self::Pro> {
72 path.clone()
73 }
74 fn cell_cod(&self, path: &Self::Cell) -> Self::Pro {
75 self.composite(path.clone()).expect("Path should have a composite")
76 }
77 fn cell_src(&self, path: &Self::Cell) -> Self::Arr {
78 path.src(UnderlyingGraph::ref_cast(&self.0))
79 }
80 fn cell_tgt(&self, path: &Self::Cell) -> Self::Arr {
81 path.tgt(UnderlyingGraph::ref_cast(&self.0))
82 }
83
84 fn compose(&self, path: Path<Self::Ob, Self::Arr>) -> Self::Arr {
85 let disc = DiscreteCategory::ref_cast(ObSet::ref_cast(&self.0));
86 disc.compose(path)
87 }
88
89 fn compose_cells(&self, tree: DblTree<Self::Arr, Self::Pro, Self::Cell>) -> Self::Cell {
90 tree.dom(UnderlyingDblGraph::ref_cast(self))
91 }
92}
93
94impl<C: FgCategory> VDCWithComposites for DiscreteDblTheory<C>
95where
96 C::Ob: Clone,
97 C::Mor: Clone,
98{
99 fn composite(&self, path: Path<Self::Ob, Self::Pro>) -> Option<Self::Pro> {
100 Some(self.0.compose(path))
101 }
102
103 fn composite_ext(&self, path: Path<Self::Ob, Self::Pro>) -> Option<Self::Cell> {
105 Some(path)
106 }
107
108 fn through_composite(&self, path: Self::Cell, range: Range<usize>) -> Option<Self::Cell> {
109 let graph = UnderlyingGraph::ref_cast(&self.0);
110 Some(path.replace_subpath(graph, range, |subpath| self.0.compose(subpath).into()))
111 }
112}
113
114impl<C: FgCategory + Validate> Validate for DiscreteDblTheory<C> {
115 type ValidationError = C::ValidationError;
116
117 fn validate(&self) -> Result<(), nonempty::NonEmpty<Self::ValidationError>> {
118 self.0.validate()
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use crate::dbl::theory::DblTheory;
126 use crate::one::{Path, fp_category::FpCategory};
127
128 #[test]
129 fn theory_interface() {
130 let mut sgn: FpCategory<char, char> = Default::default();
131 sgn.add_ob_generator('*');
132 sgn.add_mor_generator('n', '*', '*');
133 sgn.equate(Path::pair('n', 'n'), Path::Id('*'));
134
135 let th = DiscreteDblTheory::from(sgn);
136 let sgn = th.category();
137 assert!(th.has_ob_type(&'*'));
138 assert!(th.has_mor_type(&'n'.into()));
139 let path = Path::pair('n'.into(), 'n'.into());
140 assert!(sgn.morphisms_are_equal(th.compose_types(path).unwrap(), Path::Id('*')));
141
142 assert_eq!(th.hom_type('*'), Path::Id('*'));
143 assert_eq!(th.hom_op('*'), Path::single(Path::Id('*')));
144 }
145}