#[allow(unused_imports)]
use alloc::{format, string::String, string::ToString, vec, vec::Vec};
use super::adjunction::Adjunction;
use super::arrow::Arrow;
use super::category::Category;
use super::entity::{Concept, FinitelyGenerated};
use super::functor::Functor;
use super::named::NamedCategory;
use super::transformation::NaturalTransformation;
use crate::ontology::meta::OntologyName;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConnectionFamily {
Functor {
map_object: Vec<(String, String)>,
map_morphism: Vec<(String, String)>,
},
NaturalTransformation {
components: Vec<(String, String)>,
},
Adjunction {
left_map_object: Vec<(String, String)>,
right_map_object: Vec<(String, String)>,
unit: Vec<(String, String)>,
counit: Vec<(String, String)>,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConnectionGenerators {
pub name: OntologyName,
pub source: OntologyName,
pub target: OntologyName,
pub kind: String,
pub laws: Vec<String>,
pub family: ConnectionFamily,
}
fn functor_map_morphism_table<F>() -> Vec<(String, String)>
where
F: Functor,
<F::Source as Category>::Morphism: PartialEq,
{
let mut seen: Vec<<<F as Functor>::Source as Category>::Morphism> = Vec::new();
let mut table: Vec<(String, String)> = Vec::new();
for m in <F::Source as Category>::morphisms() {
let src_kind = format!("{:?}", m.kind());
if seen.iter().any(|s| format!("{:?}", s.kind()) == src_kind) {
continue;
}
seen.push(m.clone());
let image = F::map_morphism(&m);
let tgt_kind = format!("{:?}", image.kind());
table.push((src_kind, tgt_kind));
}
table
}
pub fn extract_functor<F>() -> ConnectionGenerators
where
F: Functor,
F::Source: NamedCategory,
F::Target: NamedCategory,
<F::Source as Category>::Object: FinitelyGenerated,
<F::Source as Category>::Morphism: PartialEq,
{
use super::kinds::FunctorKind;
let map_object: Vec<(String, String)> =
<<F::Source as Category>::Object as FinitelyGenerated>::variants()
.iter()
.map(|obj| {
(
obj.name().to_string(),
F::map_object(obj).name().to_string(),
)
})
.collect();
let map_morphism = functor_map_morphism_table::<F>();
let mut laws = vec![
"FunctorIdentityLaw".to_string(),
"FunctorCompositionLaw".to_string(),
];
if matches!(F::KIND, FunctorKind::FullyFaithful) {
laws.push("FunctorFaithfulLaw".to_string());
laws.push("FunctorFullOnImageLaw".to_string());
} else if matches!(F::KIND, FunctorKind::Faithful) {
laws.push("FunctorFaithfulLaw".to_string());
}
ConnectionGenerators {
name: F::meta().name,
source: <F::Source as NamedCategory>::ontology_name(),
target: <F::Target as NamedCategory>::ontology_name(),
kind: format!("{:?}", F::KIND),
laws,
family: ConnectionFamily::Functor {
map_object,
map_morphism,
},
}
}
pub fn extract_natural_transformation<N>() -> ConnectionGenerators
where
N: NaturalTransformation,
<N::SourceFunctor as Functor>::Source: NamedCategory,
<N::SourceFunctor as Functor>::Target: NamedCategory,
<<N::SourceFunctor as Functor>::Source as Category>::Object: FinitelyGenerated,
{
let components: Vec<(String, String)> = <<<N::SourceFunctor as Functor>::Source as Category>::Object as FinitelyGenerated>::variants()
.iter()
.map(|obj| {
let comp = N::component(obj);
(obj.name().to_string(), comp.meta().name.as_str().to_string())
})
.collect();
ConnectionGenerators {
name: N::meta().name,
source: <<N::SourceFunctor as Functor>::Source as NamedCategory>::ontology_name(),
target: <<N::SourceFunctor as Functor>::Target as NamedCategory>::ontology_name(),
kind: format!("{:?}", N::KIND),
laws: vec!["NaturalityLaw".to_string()],
family: ConnectionFamily::NaturalTransformation { components },
}
}
pub fn extract_adjunction<A>() -> ConnectionGenerators
where
A: Adjunction,
<A::Left as Functor>::Source: NamedCategory,
<A::Left as Functor>::Target: NamedCategory,
<<A::Left as Functor>::Source as Category>::Object: FinitelyGenerated,
<<A::Left as Functor>::Target as Category>::Object: FinitelyGenerated,
{
type C<A> = <<A as Adjunction>::Left as Functor>::Source;
type D<A> = <<A as Adjunction>::Left as Functor>::Target;
let left_map_object: Vec<(String, String)> =
<<C<A> as Category>::Object as FinitelyGenerated>::variants()
.iter()
.map(|a| {
(
a.name().to_string(),
<A::Left as Functor>::map_object(a).name().to_string(),
)
})
.collect();
let right_map_object: Vec<(String, String)> =
<<D<A> as Category>::Object as FinitelyGenerated>::variants()
.iter()
.map(|b| {
(
b.name().to_string(),
<A::Right as Functor>::map_object(b).name().to_string(),
)
})
.collect();
let unit: Vec<(String, String)> = <<C<A> as Category>::Object as FinitelyGenerated>::variants()
.iter()
.map(|a| {
(
a.name().to_string(),
A::unit(a).meta().name.as_str().to_string(),
)
})
.collect();
let counit: Vec<(String, String)> =
<<D<A> as Category>::Object as FinitelyGenerated>::variants()
.iter()
.map(|b| {
(
b.name().to_string(),
A::counit(b).meta().name.as_str().to_string(),
)
})
.collect();
ConnectionGenerators {
name: A::meta().name,
source: <C<A> as NamedCategory>::ontology_name(),
target: <D<A> as NamedCategory>::ontology_name(),
kind: format!("{:?}", A::KIND),
laws: vec!["AdjunctionTriangleLaw".to_string()],
family: ConnectionFamily::Adjunction {
left_map_object,
right_map_object,
unit,
counit,
},
}
}