Hedges' 4-kind lattice for bidirectional programming - covariant/contravariant/invariant/bivariant types with GF(3) correspondence
/plugin marketplace add plurigrid/asi/plugin install asi-skills@asi-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
The Logic of Lenses: 4-kind lattice for bidirectional programming
Cybercat Institute: Foundations of Bidirectional Programming III — Jules Hedges, September 2024
Variables have temporal direction — forwards or backwards in time:
Kind : Type
Kind = (Bool, Bool) -- (covariant, contravariant)
-- Kind Pair Scoping Rules
-- ─────────────────────────────────────────────────
-- Covariant (True, False) delete, copy
-- Contravariant (False, True) spawn, merge
-- Bivariant (True, True) all four operations
-- Invariant (False, False) none (linear)
The 4-kind lattice projects onto GF(3) via:
BIVARIANT (True, True)
↙ 0 ↘
COVARIANT CONTRAVARIANT
(True, False) (False, True)
+1 -1
↘ ↙
INVARIANT (False, False)
(linear, no trit)
| Kind | (cov, con) | Trit | Role | Operations |
|---|---|---|---|---|
| Covariant | (T, F) | +1 | Generator | delete, copy |
| Contravariant | (F, T) | -1 | Validator | spawn, merge |
| Bivariant | (T, T) | 0 | Coordinator | all four |
| Invariant | (F, F) | — | Linear | none |
Tensor : Ty (covx, conx) -> Ty (covy, cony)
-> Ty (covx && covy, conx && cony)
This IS the GF(3) multiplication table:
| +1 0 -1
─────┼─────────────────
+1 | +1 +1 0 (True && _ = depends)
0 | +1 0 -1 (bivariant preserves)
-1 | 0 -1 -1 (_ && True = depends)
When tensoring covariant (+1) with contravariant (-1):
covx && covy = True && False = Falseconx && cony = False && True = FalseThis is why +1 ⊗ -1 = 0 gives us linear/invariant behavior!
Context morphisms with kind-aware operations:
data Structure : All Ty kas -> All Ty kbs -> Type where
Empty : Structure [] []
Insert : Parity a b -> IxInsertion a as as'
-> Structure as bs -> Structure as' (b :: bs)
-- Covariant operations (forward time)
Delete : {a : Ty (True, con)} -> Structure as bs -> Structure (a :: as) bs
Copy : {a : Ty (True, con)} -> IxElem a as
-> Structure as bs -> Structure as (a :: bs)
-- Contravariant operations (backward time)
Spawn : {b : Ty (cov, True)} -> Structure as bs -> Structure as (b :: bs)
Merge : {b : Ty (cov, True)} -> IxElem b bs
-> Structure as bs -> Structure (b :: as) bs
Structure Op CRDT Operation Direction
─────────────────────────────────────────────────
Delete crdt-stop-share-buffer forward cleanup
Copy crdt-share-buffer forward duplicate
Spawn (new user joins) backward appearance
Merge crdt-connect backward unification
Insert crdt-edit linear (invariant)
Critical insight: There are TWO introduction rules for negation, with different operational semantics:
NotIntroCov : {a : Ty (True, con)} -> Term (a :: as) Unit -> Term as (Not a)
NotIntroCon : {a : Ty (cov, True)} -> Term (a :: as) Unit -> Term as (Not a)
For bivariant types, both rules apply but produce different results!
This explains why GF(3) has:
+1 negates to -1 via NotIntroCov-1 negates to +1 via NotIntroCon0 can use either rule — but they're operationally distinctNot : Ty (cov, con) -> Ty (con, cov)
The play/coplay structure of open games is precisely this bidirectionality:
┌───────────────┐
X ──→│ │──→ Y (covariant: forward play)
│ Game G │
R ←──│ │←── S (contravariant: backward coplay)
└───────────────┘
The actionable information framework maps here:
H(I_{t+1} | I^t, u) = covariant (forward prediction)
H(I_{t+1} | ξ, u) = contravariant (backward from scene)
───────────────────────────────────────────────────────────
I(ξ; I_{t+1}) = invariant (linear combination)
| Trit | Skill | Role |
|---|---|---|
| -1 | temporal-coalgebra | Contravariant observation |
| 0 | bidirectional-lens-logic | Bivariant coordination |
| +1 | free-monad-gen | Covariant generation |
Conservation: (-1) + (0) + (+1) = 0 ✓
# Typecheck bidirectional term
just bx-typecheck term.idr
# Evaluate with covariant semantics
just bx-eval-cov term.idr
# Evaluate with contravariant semantics
just bx-eval-con term.idr
# Compare operational difference
just bx-compare term.idr
entropy-sequencer - Actionable information as bidirectional flowopen-games - Play/coplay as cov/conparametrised-optics-cybernetics - Para(Lens) structurepolysimy-effect-chains - Effect interpretation as context morphismcrdt - Distributed state with bidirectional syncTrit: 0 (ERGODIC)
Home: Prof
Poly Op: ⊗
Kan Role: Adj
Color: #26D826
The skill participates in triads satisfying:
(-1) + (0) + (+1) ≡ 0 (mod 3)