Repository navigation
v0.6.0
Quivers 0.6.0 is the factor expression release: a new let-expression form that assembles indexed tensors by evaluating a body once per cell of a (multi-axis) finite-set index, categorically the left adjoint of indexing.
Headline addition
factor expressions, the left adjoint of indexing
Where arr[i_1, ..., i_n] is the elimination rule for the dependent function space I_1 × ... × I_n -> A (the right adjoint, projecting a constant kernel), factor v_1 : I_1, ..., v_n : I_n in <body> is the introduction rule: it freely generates the indexed family from a binder-parameterized body. Composing the two recovers the identity, mirroring the unit and counit of the adjunction. The construct is functorial in each index axis.
The DSL exposes two surface forms.
Uniform multi-binder form
factor v_1 : I_1, v_2 : I_2, ..., v_n : I_n in <body>
denotes the tensor of shape (|I_1|, ..., |I_n|, *body_shape) whose (i_1, ..., i_n)-th cell is <body> evaluated with v_k := i_k. The binder variables are integer-valued and visible only inside the body, mirroring the scoping rules of let in any functional language.
object Verb : 40
object Class : 4
let cell = factor v : Verb, cls : Class in coef[v, cls] * weight[cls]
Single-binder pattern-match form
When each cell of a single-axis factor carries a structurally different expression, the case form lets you state the per-index expressions side by side:
let class_probs = factor cls : Class in {
0 -> (1.0 - prob_dur) * (1.0 - prob_telic_nodur),
1 -> (1.0 - prob_dur) * prob_telic_nodur,
2 -> prob_dur * (1.0 - prob_telic_dur),
3 -> prob_dur * prob_telic_dur,
}
The case labels must cover {0, ..., |Index|-1} exactly. Gaps, duplicates, and out-of-range labels are compile-time errors, not runtime ones. This is the natural surface for structured categorical priors: distributions over a finite class set whose cells are different structurally-composed products of upstream scalar latents (binary decision trees, hierarchical mixture priors, tree-shaped topic models).
Why factor and not a plate
A plate-bound draw delta : Verb <- Normal(0.0, sigma_v) and a factor expression factor v : Verb in <body> are not interchangeable. The plate draws an |Verb|-shape tensor of independent samples from the same kernel; the factor evaluates a deterministic body once per index and assembles the results. The plate's family is exchangeable in its index; the factor's body may depend on the index in arbitrary structurally-different ways. factor becomes the right tool when the index axis is structured (a binary tree, a directed acyclic structure, a heterogeneous mixture of distinct sub-priors) and the cells are different functions of upstream latents.
Tree-structured-categorical example
A new gallery entry, Tree-Structured Categorical, exercises both forms in one program: a tree-shaped 4-way leaf probability vector built via the pattern-match form, plus a rank-2 (Verb, Class) score tensor built via the multi-binder form whose body indexes into the pattern-match factor and two ordinary plates.
Compile-time guarantees
- Multi-axis index sizes are resolved against the surrounding object environment. Non-finite index objects are rejected at compile time with a typed error citing the offending binder.
- Pattern-match labels are checked against the index cardinality. Missing, duplicate, or out-of-range labels surface as
CompileErrorat the binder source location, not as silent broadcasting bugs at runtime. - Repeated binder names within a multi-binder factor are rejected at compile time.
Compatibility
Pre-1.0 additive change: 0.5.0 -> 0.6.0. No changes to existing surface; no migration shims needed. Existing .qvr programs compile unchanged.
Other changes
- Mermaid flowcharts in seven example pages converted from the implicit
"label" --> "label"shortcut form to the explicitnodeId["label"] --> nodeId2["label2"]form so they render under mermaid 10.9+ (used by the deployed docs).
Full Changelog: v0.5.0...v0.6.0