- 1. Overview
- 2. Type Language
- 3. Type Environments
- 4. Typing Judgments
- 5. Core Typing Rules
- 6. Query Typing Rules
- 7. Condition Typing Rules
- 8. Proof Specification Typing
- 9. Subtyping
- 10. Type Equivalence
- 11. Type Checking Algorithm
- 12. Type Safety Properties
- 13. Dependent Types vs Slipstream Paths
- 14. Type System Extensions
- 15. References
This document specifies the static type system for VCL, including:
-
Type syntax and semantics
-
Typing rules for all VCL constructs
-
Type checking algorithm
-
Subtyping and type equivalence
-
Differences between dependent-type and slipstream paths
This complements VCL Formal Semantics which covers operational semantics.
The VCL type language \(\tau\) is defined by:
Represent pairs/tuples:
Example: (UUID, Timestamp) - a octad ID paired with a timestamp
Example: Octad → Bool - predicate on octads (used in WHERE clauses)
Example: List(Octad) - query results
Example: Option(Vector[n]) - optional embedding
Example: {n : Int | n > 0} - positive integers
Example: Vector dimension-indexed types:
A function that takes vectors of any dimension and returns a float (e.g., norm).
Each modality has an associated type:
| Modality | Type Signature |
|---|---|
|
\(\text{Octad} \to \text{Set}(\text{RDFTriple})\) |
|
\(\Pi n : \text{Nat}. \text{Octad} \to \text{Option}(\text{Vector}[n\))] |
|
\(\Pi d_1, \ldots, d_k : \text{Nat}. \text{Octad} \to \text{Option}(\text{Tensor}[d_1, \ldots, d_k\))] |
|
\(\text{Octad} \to \text{Set}(\text{TypeAnnotation})\) |
|
\(\text{Octad} \to \text{Option}(\text{String})\) |
|
\(\text{Octad} \to \text{List}(\text{Version})\) |
Note: Vector and tensor modalities have dependent types - the return type depends on the dimension parameters.
A type environment \(\Gamma\) is a finite map from variables to types:
Operations:
-
\(\Gamma(x)\) - lookup type of
xin \(\Gamma\) -
\(\Gamma, x : \tau\) - extend \(\Gamma\) with binding
x : τ -
\(\text{dom}(\Gamma)\) - domain of \(\Gamma\) (set of variables)
We use the following typing judgments:
| Judgment | Meaning |
|---|---|
\(\Gamma \vdash e : \tau\) |
Expression |
\(\Gamma \vdash Q : \tau\) |
Query |
\(\Gamma \vdash C : \text{Octad} \to \text{Bool}\) |
Condition |
\(\Gamma \vdash \tau : \text{Type}\) |
\(\tau\) is a well-formed type |
\(\Gamma \vdash \tau_1 \leq \tau_2\) |
\(\tau_1\) is a subtype of \(\tau_2\) |
Where:
And:
Where:
Interpretation: A dependent sum - a pair of query results r and a proof that \(\phi(r)\) holds.
\(\tau_1 \leq \tau_2\) means "\(\tau_1\) is a subtype of \(\tau_2\)" (values of type \(\tau_1\) can be used where \(\tau_2\) is expected).
Intuition: If \(\phi_1\) is stronger (more restrictive) than \(\phi_2\), then the refined type with \(\phi_1\) is a subtype.
Note: Input is contravariant, output is covariant.
Two types \(\tau_1\) and \(\tau_2\) are definitionally equal (\(\tau_1 \equiv \tau_2\)) if they are syntactically identical up to alpha-renaming.
Examples:
-
\(\text{Vector}[10\) \equiv \text{Vector}[10]]
-
\(\Pi x : \tau. \sigma \equiv \Pi y : \tau. \sigma[y/x\)]
VCL uses bidirectional type checking with two modes:
-
Synthesis (\(\Uparrow\)): Infer type of an expression
-
Checking (\(\Downarrow\)): Check expression against expected type
"In context \(\Gamma\), synthesize that expression e has type \(\tau\)"
Examples:
Input: Query Q, context \(\Gamma\)
Output: Type \(\tau\) or type error
check_slipstream_query Γ (SELECT M FROM S WHERE C) =
let τ_M = check_modalities Γ M in
let τ_S = check_source Γ S in
let τ_C = check_condition Γ C in
if τ_C ≡ (Octad → Bool) then
QueryResult[M]
else
TypeError "Condition must be predicate on Octad"Some VCL constructs support type inference:
From vector literal:
WHERE h.embedding SIMILAR TO [0.1, 0.2, 0.3]Inferred: Vector[3]
Theorem (Progress):
If \(\Gamma \vdash Q : \tau\) and Q is a closed query (no free variables), then either:
-
Qis a value, or -
\(\exists Q'. Q \rightarrow Q'\) (Q can take a step)
Theorem (Preservation):
If \(\Gamma \vdash Q : \tau\) and \(Q \rightarrow Q'\), then \(\Gamma \vdash Q' : \tau\).
Informal: Type is preserved during evaluation.
| Aspect | Slipstream Path | Dependent-Type Path |
|---|---|---|
Result Type |
\(\text{List}(\text{Octad})\) |
\(\Sigma r : \text{List}(\text{Octad}). \text{Proof}[\phi(r)\)] |
Guarantees |
Best-effort filtering |
Formally verified via ZKP |
Performance |
Fast (no proof overhead) |
Slower (proof generation) |
Use Case |
Exploratory queries |
Compliance, audits |
Type Complexity |
Simple (no dependent types) |
Complex (refinements, dependent products) |
For runtime optimization, dependent types can be erased from slipstream queries:
Dependent-type path performs full type checking with refinements. Slipstream path can use erased types for performance.
Support for flexible octad projections:
Where r is a row variable representing "possibly more modalities".
Track side effects in query execution:
Indicating the query performs IO and network operations.
-
Pierce, B. C. (2002). Types and Programming Languages. MIT Press.
-
Pierce, B. C. (ed.) (2005). Advanced Topics in Types and Programming Languages. MIT Press.
-
Chlipala, A. (2013). Certified Programming with Dependent Types. MIT Press.
-
Norell, U. (2007). Towards a practical programming language based on dependent type theory. PhD thesis, Chalmers.