The Package Category: Substitution, Not Sequencing #
Substitution vs Sequencing #
Cryptographic packages compose by oracle resolution (substitution): when
package p₁ calls an oracle, the call is resolved by package p₂'s
implementation. This is fundamentally different from Kleisli sequencing
(the composition in Fam(KlSPComp)), where one computation's output feeds
as input to the next.
| Substitution (packages) | Sequencing (Fam/Kleisli) | |
|---|---|---|
| Morphisms | Handler → Handler (higher-order) | A →ₖ B (first-order) |
| Composition | Function composition | Monadic bind |
| Crypto meaning | Oracle resolution | Data pipeline |
| PL analogy | Variable substitution | Statement sequencing |
This distinction is well-studied in programming language semantics (Fiore–Plotkin–Turi), where substitution and sequencing are related by the continuation-passing transform but are categorically distinct. All major cryptographic frameworks (CatCrypt, constructive crypto, UC, EasyCrypt) use substitution-style composition for packages.
The Package Category #
We define a category on PkgInterface where:
- Objects are package interfaces (indexed families of operation signatures)
- Morphisms
I ⟶ Jare typed handler transformers: given implementations ofI's operations, produce implementations ofJ's - Composition is function composition (= oracle resolution)
- Identity is the pass-through handler
This is the category induced by the functor TypedHandler : PkgInterface → Type
that maps each interface to its handler type (product of Kleisli arrows). In the
language of enriched category theory, it is the underlying ordinary category
of Set(TypedHandler(I), TypedHandler(J)).
Monoidal Structure #
The symmetric monoidal structure comes from the product decomposition:
TypedHandler(I ⊗ J) ≅ TypedHandler(I) × TypedHandler(J)
Since PkgInterface.tensor uses Sum on index types and Sum.elim on families,
this isomorphism is essentially definitional. The monoidal laws reduce to
Sum index manipulation (funext + cases + rfl), in contrast to the complex
fam_ext/HEq/erw proofs needed for Fam(C).
Relationship to Fam(KlSPComp) #
Fam(KlSPComp) provides the correct monoidal structure (parallel composition)
and individual Kleisli arrows for each operation. But its composition (Kleisli
bind) does NOT match cryptographic linking (oracle substitution). Packages share
Fam's monoidal structure but have their own categorical composition.
There is no functor between these categories in either direction: Fam composition is first-order (data pipeline), while package composition is second-order (handler transformation). They are related by CPS / double-negation translation but categorically distinct.
Main definitions #
TypedHandler— typed handler for an interface (product of Kleisli arrows)Category PkgInterface— the package categoryMonoidalCategory PkgInterface— parallel composition (fromSumon indices)BraidedCategory PkgInterface— interface swapping (fromSum.swap)SymmetricCategory PkgInterface— braiding is self-inverse
Implementation Note #
The MonoidalCategoryStruct is defined as a private helper and explicitly
assigned to MonoidalCategory via toMonoidalCategoryStruct. This ensures:
- Within
MonoidalCategory where, all struct fields are accessible for coherence proofs (pentagon, etc.) which are allrfl. - There is exactly ONE path to
tensorObj(no typeclass diamond), soI ⊗ Jdefinitionally equals the struct'stensorObj I J. - The braiding iso can be defined on
PkgInterface.tensor(whereSumstructure is visible) and coerced via definitional equality.
Typed Handler #
A typed oracle handler for interface I: for each operation indexed by I.ι,
a Kleisli arrow from the domain type to the codomain type.
This is the product ∏_{i : I.ι} KlSPComp(I.doms i, I.codoms i),
the "semantic content" of a package that exports interface I.
Equations
- CatCrypt.Category.TypedHandler I = ((i : I.ι) → I.doms i → CatCrypt.Core.SPComp (I.codoms i))
Instances For
Extract the left component of a handler for a tensor interface.
Instances For
Extract the right component of a handler for a tensor interface.
Instances For
Combine handlers for the left and right components into a tensor handler.
Instances For
Category Instance #
The package category: objects are PkgInterface, morphisms are handler
transformers. Composition is function composition, corresponding to
oracle resolution (substitution).
Equations
- One or more equations did not get rendered due to their size.
Monoidal Category Instance #
The MonoidalCategoryStruct is built as a private helper, then assigned to the
MonoidalCategory instance via toMonoidalCategoryStruct. This avoids:
- The typeclass diamond (separate struct instance vs derived struct)
- Elaboration depth issues with
rflfor pentagon/triangle
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Braiding and Symmetric Structure #
The braiding iso is defined on PkgInterface.tensor where Sum structure is
directly visible. It is then used in the SymmetricCategory instance via the
definitional equality I.tensor J = I ⊗ J.
Equations
- One or more equations did not get rendered due to their size.
Connection to Untyped Handlers #
The untyped Handler from PkgEval.lean handles ALL operations
(∀ op dom codom, dom → SPComp codom). TypedHandler I restricts to
a specific interface. The relationship:
- Restrict: Given an untyped handler and an interface
I, project toTypedHandler Iby evaluating at eachI-operation's signature. - Extend: Given
TypedHandler I, extend to an untyped handler by mapping non-Ioperations toSPComp.fail.
The typed version is the correct mathematical object for the SMC structure, while the untyped version is convenient for the DeepPackage evaluation bridge.
PkgImpl (σ = id) is exactly TypedHandler.
This connects the categorical framework to the Fam-based representation.
PkgImpl.ofImpls constructs a Fam morphism from componentwise implementations;
TypedHandler IS those componentwise implementations.