#[macro_export]
macro_rules! define_category {
(
$(#[$cat_meta:meta])*
pub $cat_name:ident {
entity: $entity:ident,
relation: $relation:ident,
kind: $kind:ident,
kinds: [$($(#[$kind_meta:meta])* $domain_kind:ident),* $(,)?],
edges: [$(($e_from:ident, $e_to:ident, $e_kind:ident)),* $(,)?],
composed: [$(($c_from:ident, $c_to:ident)),* $(,)?],
}
) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum $kind {
Identity,
$($(#[$kind_meta])* $domain_kind,)*
Composed,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct $relation {
pub from: $entity,
pub to: $entity,
pub kind: $kind,
}
impl $crate::category::Relationship for $relation {
type Object = $entity;
fn source(&self) -> $entity { self.from }
fn target(&self) -> $entity { self.to }
}
$(#[$cat_meta])*
pub struct $cat_name;
impl $crate::category::Category for $cat_name {
type Object = $entity;
type Morphism = $relation;
fn identity(obj: &$entity) -> $relation {
$relation { from: *obj, to: *obj, kind: $kind::Identity }
}
fn compose(f: &$relation, g: &$relation) -> Option<$relation> {
if f.to != g.from { return None; }
if f.kind == $kind::Identity { return Some(g.clone()); }
if g.kind == $kind::Identity { return Some(f.clone()); }
Some($relation { from: f.from, to: g.to, kind: $kind::Composed })
}
fn morphisms() -> Vec<$relation> {
#[allow(unused_imports)]
use $entity::*;
use $crate::category::Entity;
let mut m = Vec::new();
for c in $entity::variants() {
m.push($relation { from: c, to: c, kind: $kind::Identity });
}
$(m.push($relation { from: $e_from, to: $e_to, kind: $kind::$e_kind });)*
$(m.push($relation { from: $c_from, to: $c_to, kind: $kind::Composed });)*
for c in $entity::variants() {
m.push($relation { from: c, to: c, kind: $kind::Composed });
}
m
}
}
};
}
#[macro_export]
macro_rules! define_dense_category {
(
$(#[$cat_meta:meta])*
pub $cat_name:ident {
entity: $entity:ident,
relation: $relation:ident,
}
) => {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct $relation {
pub from: $entity,
pub to: $entity,
}
impl $crate::category::Relationship for $relation {
type Object = $entity;
fn source(&self) -> $entity { self.from }
fn target(&self) -> $entity { self.to }
}
$(#[$cat_meta])*
pub struct $cat_name;
impl $crate::category::Category for $cat_name {
type Object = $entity;
type Morphism = $relation;
fn identity(obj: &$entity) -> $relation {
$relation { from: *obj, to: *obj }
}
fn compose(f: &$relation, g: &$relation) -> Option<$relation> {
if f.to != g.from { return None; }
Some($relation { from: f.from, to: g.to })
}
fn morphisms() -> Vec<$relation> {
use $crate::category::Entity;
let variants = $entity::variants();
variants.iter()
.flat_map(|&a| variants.iter().map(move |&b| $relation { from: a, to: b }))
.collect()
}
}
};
}