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