1use crate::array::vec::VecKind;
3use crate::lax::open_hypergraph::*;
4use crate::operations::Operations;
5use crate::strict;
6
7pub trait Functor<O1, A1, O2, A2> {
14 fn map_object(&self, o: &O1) -> impl ExactSizeIterator<Item = O2>;
16
17 fn map_operation(&self, a: &A1, source: &[O1], target: &[O1]) -> OpenHypergraph<O2, A2>;
23
24 fn map_arrow(&self, f: &OpenHypergraph<O1, A1>) -> OpenHypergraph<O2, A2>;
28}
29
30pub fn define_map_arrow<
32 F: Functor<O1, A1, O2, A2> + Clone,
33 O1: Clone + PartialEq,
34 A1: Clone,
35 O2: Clone + PartialEq,
36 A2: Clone,
37>(
38 functor: &F,
39 f: &OpenHypergraph<O1, A1>,
40) -> OpenHypergraph<O2, A2> {
41 let strict_functor: DynFunctor<F, O1, A1, O2, A2> = to_dyn_functor(functor.clone());
43 let strict_f = to_strict(f.clone());
44 let strict_g = <_ as strict::functor::Functor<VecKind, O1, A1, O2, A2>>::map_arrow(
45 &strict_functor,
46 &strict_f,
47 );
48 OpenHypergraph::from_strict(strict_g)
49}
50
51pub fn to_dyn_functor<F: Functor<O1, A1, O2, A2>, O1, A1, O2, A2>(
52 functor: F,
53) -> DynFunctor<F, O1, A1, O2, A2> {
54 DynFunctor {
55 inner: functor,
56 _phantom: std::marker::PhantomData,
57 }
58}
59
60fn to_strict<O: Clone + PartialEq, A: Clone>(
61 f: OpenHypergraph<O, A>,
62) -> strict::OpenHypergraph<VecKind, O, A> {
63 f.to_strict()
64}
65
66pub struct DynFunctor<F: Functor<O1, A1, O2, A2>, O1, A1, O2, A2> {
68 inner: F,
69 _phantom: std::marker::PhantomData<(O1, A1, O2, A2)>,
70}
71
72impl<
73 F: Functor<O1, A1, O2, A2>,
74 O1: Clone + PartialEq,
75 A1: Clone,
76 O2: Clone + PartialEq,
77 A2: Clone,
78 > strict::functor::Functor<VecKind, O1, A1, O2, A2> for DynFunctor<F, O1, A1, O2, A2>
79{
80 fn map_object(
81 &self,
82 a: &strict::SemifiniteFunction<VecKind, O1>,
83 ) -> strict::IndexedCoproduct<VecKind, strict::SemifiniteFunction<VecKind, O2>> {
84 let mut sizes = Vec::new();
85 let mut values = Vec::new();
86
87 for obj in a.0 .0.iter() {
88 let iter = self.inner.map_object(obj);
89 sizes.push(iter.len());
90 values.extend(iter);
91 }
92
93 use crate::array::vec::VecArray;
94 use crate::semifinite::SemifiniteFunction;
95 let sizes = SemifiniteFunction::<VecKind, usize>(VecArray(sizes));
96 let values = SemifiniteFunction(VecArray(values));
97 strict::IndexedCoproduct::from_semifinite(sizes, values).unwrap()
98 }
99
100 fn map_operations(
101 &self,
102 ops: Operations<VecKind, O1, A1>,
103 ) -> strict::OpenHypergraph<VecKind, O2, A2> {
104 let op_iter = ops.x.0 .0.iter();
106 let source_iter = ops.a.into_iter();
107 let target_iter = ops.b.into_iter();
108
109 let mut acc: OpenHypergraph<O2, A2> = OpenHypergraph::empty();
110 for (op, (source, target)) in op_iter.zip(source_iter.zip(target_iter)) {
111 acc.tensor_assign(self.inner.map_operation(op, &source.0, &target.0))
112 }
113
114 acc.to_strict()
115 }
116
117 fn map_arrow(
118 &self,
119 f: &strict::OpenHypergraph<VecKind, O1, A1>,
120 ) -> strict::OpenHypergraph<VecKind, O2, A2> {
121 strict::functor::define_map_arrow(self, f)
122 }
123}
124
125#[derive(Clone)]
127pub struct Identity;
128
129impl<O: PartialEq + Clone, A: Clone + PartialEq> Functor<O, A, O, A> for Identity {
130 fn map_object(&self, o: &O) -> impl ExactSizeIterator<Item = O> {
131 std::iter::once(o.clone())
132 }
133
134 fn map_operation(&self, a: &A, source: &[O], target: &[O]) -> crate::lax::OpenHypergraph<O, A> {
135 OpenHypergraph::singleton(a.clone(), source.to_vec(), target.to_vec())
136 }
137
138 fn map_arrow(&self, f: &crate::lax::OpenHypergraph<O, A>) -> crate::lax::OpenHypergraph<O, A> {
139 define_map_arrow(self, f)
140 }
141}