Monoidal Diagrams

String diagrams, monoidal categories, coherence witnesses, and verification — karpal-diagram (Phase 13).

Monoidal Category Traits

karpal-diagram provides four monoidal category traits built on karpal-arrow:

TraitSuper-traitKey method
TensorArrowtensor(left, right), associator, left/right unitors
BraidingTensorbraid<A,B>() — swap tensor factors
SymmetryBraidingbraid ∘ braid = id
TraceTensortrace(morphism) — close a feedback wire
use karpal_arrow::FnA;
use karpal_diagram::{Braiding, Tensor, Trace};

// Tensor product
let parallel = FnA::tensor(
    FnA::arr(|x: i32| x * 2),
    FnA::arr(|x: i32| x + 1),
);
assert_eq!(parallel((3, 4)), (6, 5));

// Braiding
let swap = FnA::braid::();
assert_eq!(swap((7, true)), (true, 7));

// Trace (close feedback)
let traced = FnA::trace::(FnA::arr(|(a, d)| (a + d, d)));
assert_eq!(traced(7), 7);

String Diagram DSL

Diagram is a runtime string-diagram representation with these node kinds:

use karpal_diagram::Diagram;

let circuit = Diagram::box_("f", 1, 1)
    .parallel(Diagram::box_("g", 1, 1))
    .then(Diagram::swap(1, 1))
    .then(Diagram::box_("h", 2, 2));

// Text rendering
println!("{}", circuit.render_text());

// SVG rendering
println!("{}", circuit.render_svg());

Diagram Normalization

Diagrams normalize to a canonical form using these rewrite rules:

RuleEffect
FlattenSequenceFlatten nested Sequence nodes
FlattenParallelFlatten nested Parallel nodes
ElideIdentitySequenceStageRemove identity in sequence
CollapseIdentityParallelCollapse all-identity parallel branches
CancelAdjacentSwapsswap(A,B) ; swap(B,A) → id
YankCupCap(cup ⊗ id) ; (id ⊗ cap) → id
let yanked = Diagram::cup(1)
    .parallel(Diagram::identity(1))
    .then(Diagram::identity(1).parallel(Diagram::cap(1)));

let trace = yanked.normalize_with_trace();
assert_eq!(trace.normalized, Diagram::identity(1));
assert!(trace.applied(NormalizationRule::YankCupCap));

// Equivalence checking via normalization
let a = Diagram::swap(1, 2).then(Diagram::swap(2, 1));
assert!(a.equivalent_to(&Diagram::identity(3)));

Type-Level Coherence Witnesses

Monoidal coherence laws are encoded as karpal-proof::Justifies witnesses:

WitnessLaw
PentagonIdentity(α⊗id) ; α ; (id⊗α) = α ; α
TriangleIdentityρ⊗id = α ; (id⊗λ)
HexagonIdentitybraid ; α⁻¹ ; braid ; α⁻¹ = α ; braid
use karpal_diagram::coherence::verify_hexagon;
use karpal_proof::rewrite::Rewrite;

let _proof: Rewrite<((i32, u8), bool), ((u8, bool), i32), _> =
    verify_hexagon::();

Diagrammatic Rewriting Bridge

Runtime diagram normalization connects to type-level proofs via ByNormalization and ByYanking:

use karpal_diagram::coherence::{equivalent_proved, prove_yanking, ByYanking};
use karpal_proof::rewrite::Rewrite;

// Prove equivalence via normalization
let a = Diagram::swap(1, 2).then(Diagram::swap(2, 1));
let witness: Rewrite<_, _, _> =
    equivalent_proved::<(), ()>(&a, &Diagram::identity(3)).unwrap();

// Prove yanking
let yank_proof: Rewrite<_, _, ByYanking> = prove_yanking::<(), ()>(2);

Verification Integration

Coherence certificates connect to karpal-verify:

use karpal_diagram::coherence::coherence_certificates;

let certs = coherence_certificates();
assert_eq!(certs.len(), 3); // pentagon, triangle, hexagon
for cert in &certs {
    assert_eq!(cert.backend, "karpal-diagram-coherence");
}