use std::marker::PhantomData;
use super::adjunction::Adjunction;
use super::arrow::Arrow;
use super::category::Category;
use super::entity::FinitelyGenerated;
use super::functor::Functor;
use crate::logic::axiom::Axiom;
use crate::logic::proof::{SimpleCounterexample, SimpleProof, Verdict};
use crate::ontology::meta::{Citation, Label, OntologyName};
pub struct ClosureLaw<C: Category> {
_marker: PhantomData<C>,
}
impl<C: Category> ClosureLaw<C> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<C: Category> Default for ClosureLaw<C> {
fn default() -> Self {
Self::new()
}
}
impl<C> Axiom for ClosureLaw<C>
where
C: Category + 'static,
C::Morphism: PartialEq + 'static,
{
fn verify(&self) -> Verdict {
let ms = C::morphisms();
for f in &ms {
for g in &ms {
if f.target() != g.source() {
continue;
}
if let Some(h) = C::compose(f, g)
&& !ms.contains(&h)
{
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("ClosureLaw")
}
fn description(&self) -> Label {
Label::new_static("compose(f, g) = Some(h) implies h ∈ morphisms()")
}
fn citation(&self) -> Citation {
Citation::parse_static(
"Mac Lane (1971) Categories for the Working Mathematician Ch. I §1; Barr & Wells (1999) CTCS §4 sketches",
)
}
}
pub struct IdentityLaw<C: Category> {
_marker: PhantomData<C>,
}
impl<C: Category> IdentityLaw<C> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<C: Category> Default for IdentityLaw<C> {
fn default() -> Self {
Self::new()
}
}
impl<C> Axiom for IdentityLaw<C>
where
C: Category + 'static,
C::Morphism: PartialEq + 'static,
C::Object: FinitelyGenerated,
{
fn verify(&self) -> Verdict {
for obj in <C::Object as FinitelyGenerated>::variants() {
let id = C::identity(&obj);
for m in C::morphisms_from(&obj) {
let left = C::compose(&id, &m);
if left.as_ref() != Some(&m) {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
for m in C::morphisms_to(&obj) {
let right = C::compose(&m, &id);
if right.as_ref() != Some(&m) {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("IdentityLaw")
}
fn description(&self) -> Label {
Label::new_static("id_B ∘ f = f = f ∘ id_A for every morphism f: A → B")
}
fn citation(&self) -> Citation {
Citation::parse_static("Mac Lane (1971) Categories for the Working Mathematician Ch. I §1")
}
}
pub struct AssociativityLaw<C: Category> {
_marker: PhantomData<C>,
}
impl<C: Category> AssociativityLaw<C> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<C: Category> Default for AssociativityLaw<C> {
fn default() -> Self {
Self::new()
}
}
impl<C> Axiom for AssociativityLaw<C>
where
C: Category + 'static,
C::Morphism: PartialEq + 'static,
{
fn verify(&self) -> Verdict {
let ms = C::morphisms();
for f in &ms {
for g in &ms {
if f.target() != g.source() {
continue;
}
for h in &ms {
if g.target() != h.source() {
continue;
}
let fg = C::compose(f, g);
let gh = C::compose(g, h);
let left = fg.as_ref().and_then(|fg| C::compose(fg, h));
let right = gh.as_ref().and_then(|gh| C::compose(f, gh));
if left != right {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("AssociativityLaw")
}
fn description(&self) -> Label {
Label::new_static("(h ∘ g) ∘ f = h ∘ (g ∘ f) for composable triples")
}
fn citation(&self) -> Citation {
Citation::parse_static("Mac Lane (1971) Categories for the Working Mathematician Ch. I §1")
}
}
pub fn category_law_axioms<C>() -> Vec<Box<dyn Axiom>>
where
C: Category + 'static,
C::Morphism: PartialEq + 'static,
C::Object: FinitelyGenerated,
{
vec![
Box::new(ClosureLaw::<C>::new()),
Box::new(IdentityLaw::<C>::new()),
Box::new(AssociativityLaw::<C>::new()),
]
}
pub fn assert_category_laws<C>()
where
C: Category + 'static,
C::Morphism: PartialEq + 'static,
C::Object: FinitelyGenerated,
{
for law in category_law_axioms::<C>() {
if let Err(c) = law.verify() {
panic!("category law failed: {}", c.meta().name.as_str());
}
}
}
pub struct FunctorIdentityLaw<F: Functor> {
_marker: PhantomData<F>,
}
impl<F: Functor> FunctorIdentityLaw<F> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<F: Functor> Default for FunctorIdentityLaw<F> {
fn default() -> Self {
Self::new()
}
}
impl<F> Axiom for FunctorIdentityLaw<F>
where
F: Functor + 'static,
<F::Target as Category>::Morphism: PartialEq + 'static,
<F::Source as Category>::Object: FinitelyGenerated,
{
fn verify(&self) -> Verdict {
for obj in <<F::Source as Category>::Object as FinitelyGenerated>::variants() {
let id_source = F::Source::identity(&obj);
let mapped_id = F::map_morphism(&id_source);
let id_target = F::Target::identity(&F::map_object(&obj));
if mapped_id != id_target {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("FunctorIdentityLaw")
}
fn description(&self) -> Label {
Label::new_static("F(id_A) = id_{F(A)} for every source object A")
}
fn citation(&self) -> Citation {
Citation::parse_static("Mac Lane (1971) Categories for the Working Mathematician Ch. II §1")
}
}
pub struct FunctorCompositionLaw<F: Functor> {
_marker: PhantomData<F>,
}
impl<F: Functor> FunctorCompositionLaw<F> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<F: Functor> Default for FunctorCompositionLaw<F> {
fn default() -> Self {
Self::new()
}
}
impl<F> Axiom for FunctorCompositionLaw<F>
where
F: Functor + 'static,
<F::Source as Category>::Morphism: PartialEq + 'static,
<F::Target as Category>::Morphism: PartialEq + 'static,
{
fn verify(&self) -> Verdict {
let ms = F::Source::morphisms();
for f in &ms {
for g in &ms {
if f.target() != g.source() {
continue;
}
if let Some(gf) = F::Source::compose(f, g) {
let f_mapped = F::map_morphism(&gf);
let composed = F::Target::compose(&F::map_morphism(f), &F::map_morphism(g));
if composed.as_ref() != Some(&f_mapped) {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("FunctorCompositionLaw")
}
fn description(&self) -> Label {
Label::new_static("F(g ∘ f) = F(g) ∘ F(f) for composable pairs")
}
fn citation(&self) -> Citation {
Citation::parse_static("Mac Lane (1971) Categories for the Working Mathematician Ch. II §1")
}
}
pub fn functor_law_axioms<F>() -> Vec<Box<dyn Axiom>>
where
F: Functor + 'static,
<F::Source as Category>::Morphism: PartialEq + 'static,
<F::Target as Category>::Morphism: PartialEq + 'static,
<F::Source as Category>::Object: FinitelyGenerated,
{
vec![
Box::new(FunctorIdentityLaw::<F>::new()),
Box::new(FunctorCompositionLaw::<F>::new()),
]
}
pub fn assert_functor_laws<F>()
where
F: Functor + 'static,
<F::Source as Category>::Morphism: PartialEq + 'static,
<F::Target as Category>::Morphism: PartialEq + 'static,
<F::Source as Category>::Object: FinitelyGenerated,
{
for law in functor_law_axioms::<F>() {
if let Err(c) = law.verify() {
panic!("functor law failed: {}", c.meta().name.as_str());
}
}
}
pub struct FunctorFaithfulLaw<F: Functor> {
_marker: PhantomData<F>,
}
impl<F: Functor> FunctorFaithfulLaw<F> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<F: Functor> Default for FunctorFaithfulLaw<F> {
fn default() -> Self {
Self::new()
}
}
impl<F> Axiom for FunctorFaithfulLaw<F>
where
F: Functor + 'static,
<F::Source as Category>::Morphism: PartialEq + 'static,
<F::Target as Category>::Morphism: PartialEq + 'static,
{
fn verify(&self) -> Verdict {
let ms = F::Source::morphisms();
for (i, f) in ms.iter().enumerate() {
for g in ms.iter().skip(i + 1) {
if f.source() == g.source()
&& f.target() == g.target()
&& f != g
&& F::map_morphism(f) == F::map_morphism(g)
{
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("FunctorFaithfulLaw")
}
fn description(&self) -> Label {
Label::new_static("map_morphism is injective on each hom-set (faithful)")
}
fn citation(&self) -> Citation {
Citation::parse_static("Mac Lane (1971) Categories for the Working Mathematician Ch. I §4")
}
}
pub struct FunctorFullOnImageLaw<F: Functor> {
_marker: PhantomData<F>,
}
impl<F: Functor> FunctorFullOnImageLaw<F> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<F: Functor> Default for FunctorFullOnImageLaw<F> {
fn default() -> Self {
Self::new()
}
}
impl<F> Axiom for FunctorFullOnImageLaw<F>
where
F: Functor + 'static,
<F::Source as Category>::Morphism: PartialEq + 'static,
<F::Target as Category>::Morphism: PartialEq + 'static,
<F::Source as Category>::Object: FinitelyGenerated,
{
fn verify(&self) -> Verdict {
let src_objs = <<F::Source as Category>::Object as FinitelyGenerated>::variants();
let src_ms = F::Source::morphisms();
let tgt_ms = F::Target::morphisms();
for a in &src_objs {
let fa = F::map_object(a);
for b in &src_objs {
let fb = F::map_object(b);
for t in &tgt_ms {
if t.source() != fa || t.target() != fb {
continue;
}
let hit = src_ms
.iter()
.any(|f| f.source() == *a && f.target() == *b && F::map_morphism(f) == *t);
if !hit {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("FunctorFullOnImageLaw")
}
fn description(&self) -> Label {
Label::new_static(
"every target morphism between image objects is the image of a source morphism (full onto image)",
)
}
fn citation(&self) -> Citation {
Citation::parse_static("Mac Lane (1971) Categories for the Working Mathematician Ch. I §4")
}
}
pub fn fully_faithful_law_axioms<F>() -> Vec<Box<dyn Axiom>>
where
F: Functor + 'static,
<F::Source as Category>::Morphism: PartialEq + 'static,
<F::Target as Category>::Morphism: PartialEq + 'static,
<F::Source as Category>::Object: FinitelyGenerated,
{
vec![
Box::new(FunctorFaithfulLaw::<F>::new()),
Box::new(FunctorFullOnImageLaw::<F>::new()),
]
}
pub struct AdjunctionTriangleLaw<A: Adjunction> {
_marker: PhantomData<A>,
}
impl<A: Adjunction> AdjunctionTriangleLaw<A> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<A: Adjunction> Default for AdjunctionTriangleLaw<A> {
fn default() -> Self {
Self::new()
}
}
impl<A> Axiom for AdjunctionTriangleLaw<A>
where
A: Adjunction + 'static,
<<A::Left as Functor>::Source as Category>::Morphism: PartialEq + 'static,
<<A::Left as Functor>::Target as Category>::Morphism: PartialEq + 'static,
<<A::Left as Functor>::Source as Category>::Object: FinitelyGenerated,
<<A::Left as Functor>::Target as Category>::Object: FinitelyGenerated,
{
fn verify(&self) -> Verdict {
for a in
<<<A::Left as Functor>::Source as Category>::Object as FinitelyGenerated>::variants()
{
let eta_a = A::unit(&a); let f_eta = <A::Left as Functor>::map_morphism(&eta_a); let fa = <A::Left as Functor>::map_object(&a); let eps_fa = A::counit(&fa); let composed = <<A::Left as Functor>::Target as Category>::compose(&f_eta, &eps_fa);
let id_fa = <<A::Left as Functor>::Target as Category>::identity(&fa);
if composed.as_ref() != Some(&id_fa) {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
for b in
<<<A::Left as Functor>::Target as Category>::Object as FinitelyGenerated>::variants()
{
let gb = <A::Right as Functor>::map_object(&b); let eta_gb = A::unit(&gb); let eps_b = A::counit(&b); let g_eps_b = <A::Right as Functor>::map_morphism(&eps_b); let composed = <<A::Left as Functor>::Source as Category>::compose(&eta_gb, &g_eps_b);
let id_gb = <<A::Left as Functor>::Source as Category>::identity(&gb);
if composed.as_ref() != Some(&id_gb) {
return Err(Box::new(SimpleCounterexample::new(self.meta())));
}
}
Ok(Box::new(SimpleProof::new(self.meta())))
}
fn name(&self) -> OntologyName {
OntologyName::new_static("AdjunctionTriangleLaw")
}
fn description(&self) -> Label {
Label::new_static("ε_{F(A)} ∘ F(η_A) = id_{F(A)} and G(ε_B) ∘ η_{G(B)} = id_{G(B)}")
}
fn citation(&self) -> Citation {
Citation::parse_static("Mac Lane (1971) Categories for the Working Mathematician Ch. IV §1")
}
}
pub fn adjunction_law_axioms<A>() -> Vec<Box<dyn Axiom>>
where
A: Adjunction + 'static,
<<A::Left as Functor>::Source as Category>::Morphism: PartialEq + 'static,
<<A::Left as Functor>::Target as Category>::Morphism: PartialEq + 'static,
<<A::Left as Functor>::Source as Category>::Object: FinitelyGenerated,
<<A::Left as Functor>::Target as Category>::Object: FinitelyGenerated,
{
vec![Box::new(AdjunctionTriangleLaw::<A>::new())]
}
pub fn assert_adjunction_laws<A>()
where
A: Adjunction + 'static,
<<A::Left as Functor>::Source as Category>::Morphism: PartialEq + 'static,
<<A::Left as Functor>::Target as Category>::Morphism: PartialEq + 'static,
<<A::Left as Functor>::Source as Category>::Object: FinitelyGenerated,
<<A::Left as Functor>::Target as Category>::Object: FinitelyGenerated,
{
for law in adjunction_law_axioms::<A>() {
if let Err(c) = law.verify() {
panic!("adjunction law failed: {}", c.meta().name.as_str());
}
}
}