pr4xis 0.22.0

Prove your domain is correct — ontology-driven rule enforcement with category theory, logical composition, and runtime state machines
Documentation
#[allow(unused_imports)]
use alloc::{boxed::Box, format, string::String, string::ToString, vec, vec::Vec};
use core::fmt::Debug;
use core::hash::Hash;

/// A concept — a type representing a kind of thing in an ontology.
///
/// Corresponds to Guarino (2009) *Formal Ontology in Information Systems*'s
/// "universal" and OWL's "class": a shared essence that instances can
/// inhabit. In pr4xis today, a concept's *variants* play the role of both
/// finer-grained sub-concepts and (in closed-world ontologies) the only
/// individuals — there is no separate runtime individual layer.
///
/// This base trait requires finite enumeration via [`Concept::variants`]. The
/// [`FinitelyGenerated`] marker trait identifies concepts satisfying the
/// closed-world assumption — algebraically, concepts whose variants form a
/// finite generator set for a free monoid (or equivalently, a free sum
/// type / coproduct). All pr4xis concepts today are finitely generated;
/// future open-world work will relax `Concept` to drop `variants()` and
/// move it to `FinitelyGenerated`.
///
/// Can be derived for enums with unit variants:
/// ```text
/// use pr4xis::category::Concept;
///
/// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Concept)]
/// enum Color { Red, Green, Blue }
///
/// assert_eq!(Color::variants().len(), 3);
/// ```
///
/// # Literature
///
/// - Guarino (2009) §2 — concepts as specifications of conceptualizations
/// - Masolo et al. (2003) WonderWeb D18 — DOLCE's universal/particular split
/// - Smith (2015) *Basic Formal Ontology* — continuants and occurrents
/// - ONTOLEX-Lemon (W3C 2016) — names as lexical entries
/// - Mac Lane (1971) III.5 — coproducts (sum types) and their generators
pub trait Concept: Sized + Clone + Eq + Hash + Debug + 'static {
    /// All variants of this concept — the generators of its free sum type.
    ///
    /// Algebraically, the variants ARE the generators: a concept enum is
    /// the coproduct (Mac Lane III.5) over its variants, and `variants()`
    /// returns that generator set. When the set is finite, the concept is
    /// finitely generated ([`FinitelyGenerated`]).
    fn variants() -> Vec<Self>;

    /// The Lemon canonical form identifying a variant — generated by the
    /// derive macro from the variant's Rust name. Override to inject
    /// structured lexical metadata.
    fn name(&self) -> &'static str {
        ""
    }
}

/// Marker trait for [`Concept`]s whose variants form a **finite generator
/// set** for a free monoid (equivalently, a free sum type / coproduct with
/// a finite generator family).
///
/// # Why this exists
///
/// "Finitely generated" is the standard algebraic / categorical term for
/// a structure whose elements are producible by applying operations to a
/// finite generator set. It's load-bearing across algebra and category
/// theory:
///
/// - **Lang** *Algebra* (3rd ed., Graduate Texts in Math 211, 2002) §I.2
///   — finitely generated groups / modules / algebras
/// - **Howie** *Fundamentals of Semigroup Theory* (1995) §1.2 — "a monoid
///   M is finitely generated iff there exists a finite subset S ⊂ M such
///   that every element of M can be written as a product of elements of S"
/// - **Clifford & Preston** *The Algebraic Theory of Semigroups* (1961)
///   Ch. 1 — same definition for semigroups
/// - **Mac Lane** *Categories for the Working Mathematician* (1971) VII.3
///   — free monoids and generators; III.5 — coproducts as free sum types
/// - **Adámek & Rosický** *Locally Presentable and Accessible Categories*
///   (1994) — finitely presentable / finitely generated objects
/// - **Fong & Spivak** *Seven Sketches in Compositionality* (2019) Ch. 3
///   — finitely presented categories via generators and relations
/// - **Eilenberg** *Automata, Languages, and Machines* (1974) A.III — free
///   monoids on finite alphabets, the canonical finitely-generated case
/// - **Ganter & Wille** *Formal Concept Analysis* (1999) — concepts
///   generated by (finite) attribute sets
///
/// # In pr4xis
///
/// Today every `Concept` is finitely generated — the trait requires
/// `variants() -> Vec<Self>`. This marker identifies the literature-aligned
/// structural position: closed-world concepts (Reiter 1978 *On Closed World
/// Data Bases*) are the finitely-generated case. Open-world concepts
/// (potentially-infinite or runtime-instantiated) would drop this trait
/// once `variants()` moves here.
pub trait FinitelyGenerated: Concept {}

/// Blanket impl: every concept today is finitely generated.
impl<T: Concept> FinitelyGenerated for T {}

/// Metadata about concept variants — generated by the derive macro
/// from `/// doc comments`. Separate from the [`Concept`] trait because
/// descriptions are metadata ABOUT the concept, not behavior OF it.
///
/// The derive macro generates a const `<TypeName>_META: &[ConceptMeta]`
/// for each concept enum. The vocabulary system reads it.
#[derive(Debug, Clone)]
pub struct ConceptMeta {
    pub name: &'static str,
    pub description: &'static str,
}

#[cfg(test)]
mod tests {
    use super::*;
    use pr4xis_derive::Concept;

    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Concept)]
    enum TestConcept {
        A,
        B,
        C,
    }

    #[test]
    fn derive_concept_produces_all_variants() {
        let v = TestConcept::variants();
        assert_eq!(v.len(), 3);
        assert_eq!(v[0], TestConcept::A);
        assert_eq!(v[1], TestConcept::B);
        assert_eq!(v[2], TestConcept::C);
    }

    #[test]
    fn derive_concept_single_variant() {
        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Concept)]
        enum Single {
            Only,
        }
        assert_eq!(Single::variants(), vec![Single::Only]);
    }

    #[test]
    fn every_concept_is_finitely_generated_today() {
        fn check<T: FinitelyGenerated>(_t: &T) {}
        check(&TestConcept::A);
    }
}