Linear
Linear type constructors: structural guards for capability tokens.
Pure type predicates that check token structure without consuming. Usage enforcement is in effects/linear.nix (separate concerns).
Linear(T) — exactly one consume required Affine(T) — at most one consume (release allowed) Graded(n, T) — exactly n consumes (generalizes Linear/Affine)
See Orchard et al. (2019) for graded modal types and Pedrot & Tabareau (2020) "Fire Triangle" for the types/effects split.
Affine
Affine type: capability token that may be consumed at most once.
Affine : Type -> Type
Structurally identical to Linear(T). The name communicates that the
resource may be explicitly released (dropped) via effects/linear.release
without consuming it — "at most once" vs Linear's "exactly once."
The structural guard is the same: both check for a valid capability token with inner type T. The usage distinction (exactly-once vs at-most-once) is enforced by the effect handler, not the type system.
Operations:
.check v— pure guard: is v a valid affine token wrapping T?.validate v— effectful: sendstypeCheckfor blame tracking.innerType— the wrapped type T
Graded
Graded type: capability token with usage multiplicity annotation.
Graded : { maxUses : Int | null, innerType : Type } -> Type
Generalizes Linear and Affine via a maxUses parameter:
Graded { maxUses = 1; innerType = T; } # ≡ Linear(T)
Graded { maxUses = null; innerType = T; } # ≡ Unlimited(T)
Graded { maxUses = n; innerType = T; } # ≡ Exact(n, T)
The structural guard is the same as Linear and Affine — token
structure with inner type check. The maxUses appears in the type
name for documentation but is NOT checked by the guard (the grade
lives in handler state, not the token).
The name uses ω for null (unlimited):
Graded(1, Int), Graded(5, String), Graded(ω, Bool)
From Orchard et al. (2019) "Quantitative Program Reasoning with Graded Modal Types" — semiring-indexed usage annotations where + models branching, × models sequencing, 1 = linear, ω = unlimited.
Operations:
.check v— pure guard: is v a valid graded token wrapping T?.validate v— effectful: sendstypeCheckfor blame tracking.innerType— the wrapped type T.maxUses— the declared usage multiplicity
Linear
Linear type: capability token that must be consumed exactly once.
Linear : Type -> Type
Creates a type whose check verifies the capability token structure:
{ _linear = true, id = Int, resource = innerType }
Pure structural guard — checking does not consume the token.
effects/linear.nix tracks consumption separately.
Adequacy invariant:
Linear(T).check v ⟺ all typeCheck effects in Linear(T).validate v pass
Holds by construction via mkType's auto-derived validate.
Operations:
.check v— pure guard: is v a valid linear token wrapping T?.validate v— effectful: sendstypeCheckfor blame tracking.innerType— the wrapped type T