A Programming Language for Virtual
Double Theories
Virtual Workshop on Double Categories · November 5, 2026
\[ % https://tex.stackexchange.com/a/269194 \newcommand{\proto}{\mathrel{\mkern3mu\vcenter{\hbox{$\scriptstyle+$}}\mkern-13mu{\to}}} \]
We are often interested in presenting (first-order, algebraic, etc.) theories by some small collection of operation symbols and relations between them.
Definition:
The signature of a theory is the collection of operation symbols.
The axioms of a theory are the equalities or formulas relating those symbols.
Idea:
The signature is an interface.
The axioms are a description of the interface’s behavior.
A model of a theory is a concrete interpretation of the symbols in the signature which satisfy the axioms.
In categorical logic we are interested in viewing theories themselves as categorical structures.
Idea: many theories can be expressed as double categories; their models are naturally valued in categories (Lambert and Patterson 2024).
These can likewise be presented via a signature and axioms:
Our double theories will be virtual, meaning they are represented as virtual double categories.
Like ordinary double categories the tight direction is still a (strict) category. Cells map from a path of (zero or more) proarrows, into a single proarrow:
Tight composition is defined for compatible cells.
Loose composition and loose units are additional universal properties that a VDC may or may not have. For now we will ignore these, but be emotionally prepared for them to show up in some examples later.
Our VDCs will be fibrational, meaning they admit restrictions.
Given a proarrow \(P : X' \proto Y'\) and tight morphisms \({f : X \to X'},\) \({g : Y \to Y'},\) there is a cartesian cell
We say that \(P(f;g)\) is the restriction of \(P\) along \(f\) and \(g\).
There is a mechanical procedure for constructing a type theory over the internal languages of models of a virtual double theory (Lynch and Patterson 2026).
Example: there is a simple presentation for the double theory of database schemas consisting of a single proarrow. This induces a type theory for the internal language of databases over a given schema.
CatColab, the Topos Institute’s a scientific modeling ecosystem, uses this idea to implement a uniform type system across many application domains.
Goal: develop a domain-specific programming language (DSL) for specifying virtual double theories, so that users can work with any the categorical logic in CatColab.
We want to prevent the user from specifying a malformed theory, so we will use a type theory for VDCs to eliminate bugs.
Our type theory is an extension of FVDblTT (Nasu 2025), which proposes a type theory for reasoning in the internal language of cartesian fibrational virtual double categories. Our setup differs in a few ways, in order to more readily facilitate our software implementation for (finitely presented) virtual double theories:
| Judgment | Notation |
|---|---|
| \(\mathrm{Type}\) | \(X \text{ ty}\) |
| \(\mathrm{Context}\) | \(\Gamma \text{ ctx}\) |
| \(\mathrm{Term}\) | \(\Gamma \vdash s : X\) |
| \(\mathrm{Protype}\) | \(\Gamma_0 , \Gamma_1 \vdash \underline{P} \text{ proty}\) |
| \(\mathrm{Boundary}\) | \(\Gamma_0, \dots, \Gamma_n \mid \underline{P}_1, \dots, \underline{P}_n \to \underline{Q}\) |
| \(\mathrm{Procontext}\) | \(\Gamma_0, \dots, \Gamma_n \mid p_1 : \underline{P}_1, \dots, p_n : \underline{P}_n \text{ proctx}\) |
| \(\mathrm{Substitution}\) | \(\overline{\Gamma} \mid \Omega \vdash \{s_0, \dots, s_n\}(\tau_1, \dots, \tau_n) : (\underline{P}_1, \dots, \underline{P}_n)\) |
| \(\mathrm{Proterm}\) | \(\overline{\Gamma} \mid \Omega \vdash \tau : \underline{P}\) |
(Here \(\overline{\Gamma}\) is shorthand for \(\Gamma_0, \dots, \Gamma_n,\) and \(\Omega\) for \(p_1 : \underline{P}_1, \dots, p_n : \underline{P}_n\).)
The signature \(\Sigma\) of a virtual double category consists of:
Types are merely object symbols:
\[ \frac{X \in \mathcal{T}_\Sigma}{X \text{ ty}} \]
Term contexts are unary, consisting of exactly one variable binding:
\[ \frac{X \text{ ty}}{(x : X) \text{ ctx}} \]
Terms are typed by term contexts. The type theory for terms forms a (cut-free) unary type theory for categories (Shulman 2016):
\[ \frac{X \text{ ty}}{x : X \vdash x : X} \]
\[\frac{\Gamma \vdash s : X \quad f \in \mathcal{F}_\Sigma(X, Y)}{\Gamma \vdash f(s) : Y} \]
Given morphisms \[ X \xrightarrow{f} Y \xrightarrow{g} Z \xrightarrow{h} W \] the composite \(h \circ (g \circ f) = (h \circ g) \circ f\) has the unique representation (up to \(\alpha\)-equivalence) \[ x : X \vdash h(g(f(x))) : W. \]
The identity at \(X\) is represented by \[ x : X \vdash x : X. \]
Each proarrow symbol in \(\mathcal{P}_\Sigma\) gives rise to a dependent family of “protypes”:
\[ \frac{\Gamma_0 \vdash s : X \quad \Gamma_1 \vdash t : Y \quad P \in \mathcal{P}_\Sigma(X, Y)}{\Gamma_0, \Gamma_1 \vdash P(s, t) \text{ proty}} \]
(We abbreviate \(P(s, t)\) by \(\underline{P}\) when \(s\) and \(t\) are not relevant.)
Recall that \(s\) and \(t\) represent tight morphisms. The protype \(P(s, t)\) represents the restriction of the proarrow \(P\) along \(s\) and \(t.\)
Recall: each cell symbol \(\alpha \in \mathcal{C}_\Sigma\) is associated with a boundary. These are judgments of the form \[ \frac{\begin{matrix}x_{i - 1} : X_{i - 1}, x_i : X_i \vdash \underline{P}_i \text{ proty} \quad (i = 1, \dots, n) \\ x_0 : X_0, x_n : X_n \vdash \underline{Q} \text{ proty}\end{matrix}}{\alpha : (x_0 : X_0, \dots, x_n : X_n \mid \underline{P}_1, \dots, \underline{P}_n) \to \underline{Q}} \]
We say that \(\alpha\) has arity \(n\), with domain \(\underline{P}_1, \dots, \underline{P}_n\) and codomain \(\underline{Q}.\)
The “procontext” that a cell (“proterm”) is typed in represents a path of zero or more proarrows:
These are formed inductively, as a sequence of protypes with contexts matching at common junctures:
\[ \frac{\Gamma \text{ ctx}}{\Gamma \mid \cdot \text{ proctx}} \hspace{2em} \frac{\overline{\Gamma}_L, \Gamma \mid \Omega \text{ proctx} \quad \Gamma, \Gamma_R \vdash \underline{P} \text{ proty}}{\overline{\Gamma}_L, \Gamma, \Gamma_R \mid \Omega, p : \underline{P} \text{ proctx}} \]
Note: both components of procontexts are ordered. The proterm component is also linear, meaning that each proterm variable must be used exactly once.
Types and terms represented objects and (tight) morphisms of the VDC.
Proarrows behave like objects with a source and target—these should correspond to types (“protypes”) with a certain kind of dependency, as we’ve seen.
Cells are like \(n\)-ary maps between proarrows, so these should be terms (“proterms”) constructed as trees of cell symbols. Like the syntax for terms, our syntax for proterms will be pointful.
The (tight) identity cell on a proarrow \(P\) is represented by the typing judgment for a proterm variable: \[ \frac{\Gamma_0, \Gamma_1 \vdash \underline{P} \text{ proty}}{\Gamma_0, \Gamma_1 \mid p : \underline{P} \vdash p : \underline{P}} \]
Like the variables in the unary type theory for terms, these are the leaves of proterm typing derivations.
Note: a proterm variable \(p : P(f(x), g(y))\) simultaneously represents the identity on \(P(f;g)\) and the cartesian cell
In this way the syntax of the language normalizes the fibrational structure of a virtual equipment.
We represent the input to an \(n\)-ary cell as a sequence of proterms of length \(n\) which have compatible boundary terms (tight morphisms): \[ \frac{\Gamma_0 \vdash s_0 : X_0}{\Gamma_0 \mid \cdot \vdash \{s_0\}() : ()} \]
Cell generators are applied to substitutions of the correct form:
Note that the term arguments \(s_0, \dots, s_n\) allow the domain protypes to be restricted. The idea is that a protype \(P(f(x), g(y))\) should be thought of as a “subtype” of \(P(x', y'),\) for example.
\[ x : X, y : Y \mid p : P(x, y) \vdash p : P(x, y) \]
\[ \frac{\begin{matrix}\alpha : (x : X, y : Y \mid P(x, y)) \to M(f(x), g(y)) \\ x : X, y : Y \mid p : P(x, y) \vdash \{x, y\}(p) : (P(x, y)) \end{matrix}}{x : X, y : Y \mid p : P(x, y) \vdash \alpha\{x, y\}(p) : M(f(x), g(y))} \]
Objects
Cells
Axioms
Proarrow isomorphisms are syntactic sugar for a pair of cell declarations and a pair of axioms making them inverses.
The theory of promonads is a unital VDC with an object \(X\), a proarrow \({P : X \proto X}\) such that the loose composite \(P \odot P\) is defined and is equal to \(P\), and a virtual cell \(\theta\):
subject to the following axioms:
We can specify this theory in our DSL via
One presentation for the theory of adjunctions is specified by a pair of objects \(X, Y\) and tight morphisms \({f : X \to Y}\) (the left adjoint) and \({g : Y \to X}\) (the right adjoint), together with inverse cells
where \(\mathrm{id}\) denotes the loose unit and \(1\) denotes the tight unit.
We can describe this theory in our programming language with
and cells
(if he is not already doing The Demo™ you should politely remind him to do The Demo™)
In the two example theories we needed to use both loose units and loose composites. For illustrative purposes we defined these manually, but ideally they should be primitives in the language.
Problem: loose units and composites satisfy universal properties, which impose a huge number of axioms.
Goal: capture these axioms with the language’s operational semantics, so that applying the universal properties becomes a normalization procedure.
This is hard. :(
Many theories use modalities (read: well-behaved double monads). For instance, one can give a presentation of the theory of monoidal categories using the list modality, replacing the monoidal identity and binary tensor product with a single tight morphism \[ \otimes : \mathrm{List}(X) \to X. \]
Idea: take the closure of the generators under modal application, and introduce primitive cells for the monad unit and multiplication.
Problem: the monad laws demand some computational mechanism to handle equalities of tight morphisms, which induce equalities of (pro)types. Judgmental equalities between types famously make type-checking hard.