use crate::category::arrow::Arrow;
use crate::category::entity::Concept;
use crate::category::{Category, Morphism as CategoryMorphism};
use crate::ontology::meta::{ConceptName, Morphism as MetaMorphism, MorphismKind};
pub fn reify_concept<O: Concept>(obj: &O) -> ConceptName {
let name = obj.name();
if name.is_empty() {
ConceptName::new(format!("{obj:?}"))
} else {
ConceptName::new(name.to_string())
}
}
pub fn reify_kind<K: core::fmt::Debug>(kind: &K) -> MorphismKind {
let kind_id = format!("{kind:?}");
match kind_id.as_str() {
"Identity" => MorphismKind::Identity,
"Subsumption" => MorphismKind::Subsumption,
"Parthood" => MorphismKind::Parthood,
"Causation" => MorphismKind::Causation,
"Opposition" => MorphismKind::Opposition,
"Equivalence" => MorphismKind::Equivalence,
_ => MorphismKind::Custom(std::borrow::Cow::Owned(kind_id)),
}
}
pub fn reify<C>(m: &CategoryMorphism<C>) -> MetaMorphism
where
C: Category,
C::Object: Concept,
C::Morphism: Arrow<Object = C::Object>,
<C::Morphism as Arrow>::Kind: core::fmt::Debug,
{
MetaMorphism::new(
reify_concept(&m.source()),
reify_concept(&m.target()),
reify_kind(&m.inner().kind()),
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::category::entity::FinitelyGenerated;
use crate::category::{Arrow, Category};
use crate::ontology::meta::MorphismKind;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Obj {
A,
B,
}
impl Concept for Obj {}
impl FinitelyGenerated for Obj {
fn variants() -> Vec<Self> {
vec![Obj::A, Obj::B]
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Kind {
Identity,
Subsumption,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Morph {
from: Obj,
to: Obj,
kind: Kind,
}
impl Arrow for Morph {
type Object = Obj;
type Kind = Kind;
fn source(&self) -> Obj {
self.from
}
fn target(&self) -> Obj {
self.to
}
fn kind(&self) -> Kind {
self.kind
}
}
struct TestCat;
impl Category for TestCat {
type Object = Obj;
type Morphism = Morph;
fn identity(obj: &Obj) -> Morph {
Morph {
from: *obj,
to: *obj,
kind: Kind::Identity,
}
}
fn compose(_f: &Morph, _g: &Morph) -> Option<Morph> {
None }
fn morphisms() -> Vec<Morph> {
vec![
Morph {
from: Obj::A,
to: Obj::A,
kind: Kind::Identity,
},
Morph {
from: Obj::A,
to: Obj::B,
kind: Kind::Subsumption,
},
]
}
}
#[test]
fn reify_projects_identity() {
let id = TestCat::identity(&Obj::A);
let handle = CategoryMorphism::<TestCat>::of(id);
let reified = reify(&handle);
assert_eq!(reified.kind, MorphismKind::Identity);
assert_eq!(reified.from, reified.to);
}
#[test]
fn reify_projects_subsumption() {
let sub = Morph {
from: Obj::A,
to: Obj::B,
kind: Kind::Subsumption,
};
let handle = CategoryMorphism::<TestCat>::of(sub);
let reified = reify(&handle);
assert_eq!(reified.kind, MorphismKind::Subsumption);
}
#[test]
fn reify_kind_maps_canonical_variants() {
#[derive(Debug)]
#[allow(dead_code)]
enum K {
Subsumption,
Parthood,
Unknown,
}
assert_eq!(reify_kind(&K::Subsumption), MorphismKind::Subsumption);
assert_eq!(reify_kind(&K::Parthood), MorphismKind::Parthood);
assert!(matches!(reify_kind(&K::Unknown), MorphismKind::Custom(_)));
}
}