cubical-transport-hott-lean4/CubicalTransport/Modal.lean
Maximus Gorog 391a048dcf
Some checks failed
Lean Action CI / build (push) Has been cancelled
Layer 3.3a: substantive unit/counit + typed-correctness for adjoint triple
Adds substantive content to Modal.lean §2a/§2b without discharging
the §3 adjoint theorems (which wait on FS-H18, see paired topolei
commit).

§2a — Unit/counit underlying CTerm constructions (substantive):
  · flatSharpUnit  : λ$a. modalIntro .sharp (modalIntro .flat $a)
                     — A → ♯(♭ A)
  · flatSharpCounit: λ$x. modalElim .flat (λ$y. modalElim .sharp
                            (λ$z. $z) $y) $x
                     — ♭(♯ A) → A
  · shapeFlatUnit  : λ$a. modalIntro .flat (modalIntro .shape $a)
                     — A → ♭(ʃ A)
  · shapeFlatCounit: λ$x. modalElim .shape (λ$y. modalElim .flat
                            (λ$z. $z) $y) $x
                     — ʃ(♭ A) → A
  Reserved binders modalUnitVar / modalCounitVar / modalCounitInner /
  modalCounitCore.  Real CTerm bodies using actual modal constructors
  (Phase 2 unification); no placeholders.

§2b — Constructive partial discharges (no FS-H18 needed, REAL proofs):
  · 4 @[simp] rfl-lemmas: flatSharpUnit_eq / flatSharpCounit_eq /
    shapeFlatUnit_eq / shapeFlatCounit_eq pinning each body.
  · 4 typed-correctness theorems: flatSharpUnit_typed /
    flatSharpCounit_typed / shapeFlatUnit_typed / shapeFlatCounit_typed
    discharge HasType obligations via HasType.lam +
    HasType.modalIntro (units) or chained HasType.modalElim with
    explicit (var, A, C, k) annotations (counits).
  · 4 non-vacuity / non-degeneracy theorems:
    flatSharpUnit_ne_Counit, shapeFlatUnit_ne_Counit,
    flatSharpUnit_ne_shapeFlatUnit, flatSharpCounit_ne_shapeFlatCounit
    — distinct binder names / kind heads make the constructions
    genuinely distinct (rules out vacuous defs).

§3 — Adjoint theorem annotations updated:
  · flat_sharp_adjoint / shape_flat_adjoint / cohesive_triple sorry'd
    with sharper FS-H18 attribution.  Each annotation names the
    §2a/§2b constructive partial discharges that ARE landed and
    explains exactly what FS-H18 unlocks (CAdjoint instance via
    triangle identities = Path-form of the modal β-rules).
  · 3 sorries in proof positions (lines 880, 909, 985) — same count
    as before, sharper attribution.

The CTerm un-indexed-by-universe nature of Syntax.lean §3 means
flatSharpUnit etc.'s (ℓ, A) arguments are formally unused in the
body; explicit `let _ := ℓ; let _ := A` makes this intentional and
keeps the signature aligned with the typed-correctness theorems.

Build: lake build (48 jobs) + lake build CubicalTransport (43 jobs)
PASS.  Runtime: 49/49 + 46/46 = 95/95.

ZERO new sorries (the §2b theorems are all REAL proofs).  ZERO
new noncomputable / Classical / axiom.

Modal.lean: 598 → 1026 lines (+428).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 06:32:39 -06:00

1026 lines
49 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
CubicalTransport.Modal
======================
Modal type theory layer (THEORY.md §3.2 / §3.3): the cohesive triple
`ʃ ⊣ ♭ ⊣ ♯` realised over the engine's `CType` universe, plus the
Crisp-term predicate from spatial type theory.
Refactor Phase 3 of the elegance pass. The engine's modal layer was
unified in Refactor Phase 2: the nine ad-hoc per-modality
constructors (3 CType + 6 CTerm) collapsed into three unified ones
(`CType.modal`, `CTerm.modalIntro`, `CTerm.modalElim`) parameterised
by `ModalityKind`. Phase 3 — this file — finishes the cascade by
rewriting the modal cohesion content against the unified
constructors directly. No transient aliases remain.
The structure of the file:
§1. One modal *functor* witness, `forModalityKind`, on
`CType_as_Category `, parameterised by `k : ModalityKind`.
Replaces the prior trio (`flatFunctor` / `sharpFunctor` /
`shapeFunctor`), which were three syntactic copies of the
same construction differing only in which constructor of
`ModalityKind` they instantiated. The `obj` and `arr`
fields translate universe-level morphisms (paths in the
universe) through the modality of kind `k`.
§1a. Substantive-dependence rfl-lemmas + dependence theorems for
`forModalityKind`, parameterised over `k`.
§2. The `Crisp : CTerm → Prop` predicate from spatial type
theory: a CTerm is crisp when it is introduced via a modal
elimination path. The constructors are inductive and
parameterised over `k : ModalityKind` — semantically, every
modal eliminator extracts a value from a modalised type and
the result is crisp by construction (the discrete /
shape-localised / codiscrete cases all share the same
introduction discipline at the predicate level).
§2a. **Substantive unit / counit underlying CTerms** for the two
adjunctions of the cohesive triple — `flatSharpUnit`,
`flatSharpCounit`, `shapeFlatUnit`, `shapeFlatCounit`. Each
is a concrete `CTerm` whose body is built from the unified
modal constructors `.modalIntro k` / `.modalElim k` (no
placeholders). These are the *underlying functions* that
the natural-transformation components project to once the
Path-equality lift (FS-H18) lands; downstream code can
already reference them as concrete defs.
§2b. **Constructive partial discharges** of the adjunction
content that does *not* require FS-H18: the typed-correctness
theorems `flatSharpUnit_typed`, `flatSharpCounit_typed`,
`shapeFlatUnit_typed`, `shapeFlatCounit_typed`, plus
substantive-dependence checks for the unit/counit CTerms.
These are real Lean proofs (not sorries) that pin down
the Π-type signature of each unit/counit and witness
non-vacuity.
§3. Three substantive Prop-valued *adjoint-triple* theorems:
`flat_sharp_adjoint`, `shape_flat_adjoint`,
`cohesive_triple` — each stating real adjointness content
using the engine's `CAdjoint` and `LexModality` frameworks
and the unified `forModalityKind`. The proofs are sorry'd
and each sorry now points at the specific FS-H18 hypothesis
(modal Path-equality lift) in `topolei/docs/HYPOTHESES.md`,
which is the precise constructive blocker. The unit/counit
components are no longer abstract data — they are the
concrete CTerms of §2a, awaiting only the Path-form lift to
package as full `CNatTrans` records.
§4. One soundness theorem for the modal β-rule:
`modal_beta_sound`. Records the Phase 1 eval β-axiom as
an Eq fact at the theorem level so downstream tactics may
rewrite with it. Replaces the prior trio (`flat_beta_sound`
/ `sharp_beta_sound` / `shape_beta_sound`), which were
three definitional copies of the same axiom instantiated
at distinct `ModalityKind` cases.
§5. The barrel update lives in `CubicalTransport.lean`.
## Scope decision: CContext.crispVar deferred
The full §3.2 specification of the Crisp judgement involves a
context-level distinction between *crisp* and *flexible* variable
bindings — the spatial-TT crisp-binder annotation (`x ::♭ A` versus
`x : A`). Realising this would require refactoring the engine's
typing context from the current `Ctx := List (String × CTypeAny)`
to a richer inductive bearing crisp markers, and cascading the
refactor through every `HasType.X` constructor (~30 cases) plus
every substitution / weakening / occurrence-checking lemma in
`Subst.lean` / `DimLine.lean`.
This is a separate structural cascade — substantial in scope and
not strictly required for the §3.3 adjunction theorems (which are
CType-level adjointness statements: they range over the `CType `
category, not over the typing-context judgement). Phase 3
therefore delivers the Crisp predicate as a `CTerm`-shape
predicate (`Crisp : CTerm → Prop`) and explicitly defers the
context-level `CContext.crispVar` refinement to a subsequent
phase. See THEORY.md §3.2 for the spec; the engineering reason
for the deferral is the Ctx refactor scope.
This is an **honest deferral, not a shortcut.** All three
adjunction theorems below state real Prop content; the Crisp
predicate's term-level constructor below is substantive (it
classifies the head shape of `modalElim`-derived terms in a way
that distinguishes those from `modalIntro`-only or `var`-only
CTerms).
Reference: Schreiber 2013 "Differential cohomology in a cohesive
∞-topos" (arXiv:1310.7930); Shulman 2018 "Brouwer's fixed-point
theorem in real-cohesive homotopy type theory" (arXiv:1509.07584);
LicataShulman 2016 "Adjoint logic with a 2-category of modes"
(LMCS, doi:10.1007/978-3-319-45283-7_15).
-/
import CubicalTransport.Modality
import CubicalTransport.Category
import CubicalTransport.Typing
import CubicalTransport.Eval
namespace CubicalTransport.Modal
open CubicalTransport.Modality
-- ── §1. The modal functor, parameterised by `ModalityKind` ─────────────────
--
-- A single endofunctor `forModalityKind k` on `CType_as_Category `,
-- parameterised by `k : ModalityKind`. Replaces the Phase-1 trio
-- `flatFunctor` / `sharpFunctor` / `shapeFunctor`, which were three
-- syntactic copies of the same construction differing only in their
-- instantiation of `ModalityKind`. The construction is uniform in
-- `k`: the modality enters through the unified constructors
-- `.modalIntro k`, `.modalElim k`.
--
-- The universe-as-category has:
-- · objects = CTerms inhabiting `.univ ( := )` — concretely, codes
-- of types via `.code A`.
-- · morphisms = paths in the universe `.path .univ A B`, applied
-- function-style via `λ$y. q ($y)` (Category.lean's `comp`).
--
-- The `obj` field of the modal functor takes the code of `A : CType `
-- to the code of the modalised type. Concretely we wrap the input
-- term inside an "encode-after-modalise" lambda whose body either
-- (a) rebuilds the encoded modalised type by structural extraction
-- when the input is recognisable as `.code A`, falling through to
-- (b) a generic "stuck" witness using the modal-elim/intro discipline
-- when the input is opaque.
--
-- Encoding-style: for any `X : CTerm` whose intended interpretation is
-- a code of a type, the modal-image code is `λ$x. M (X applied at $x)`
-- where `M` is the modality of kind `k`. At the engine level we
-- can't peek inside `X` (it is an opaque CTerm), so we encode the
-- modalisation via the intro/elim discipline that holds for every
-- modality — the same shape regardless of `k`:
--
-- `(forModalityKind k).obj X = .lam "$x" (.modalIntro k (.app X (.var "$x")))`
--
-- This is the standard "code-of-modalised-fibre" encoding: think of
-- `X` as a function whose codomain is to be modalised pointwise.
-- The encoding is *substantive* in both `X` and `k` — distinct `X`s
-- yield distinct lambda bodies (because `.app X _` is syntactically
-- present), and distinct `k`s yield distinct `.modalIntro` heads.
--
-- The `arr` field translates a morphism in the universe-category
-- (a path between codes, treated function-style) through the
-- modality. Concretely, given `f : A → B`, the modal-image is the
-- function `M A → M B` defined by elim-then-intro discipline:
-- λ$m. M.elim (λ$y. M.intro (f $y)) $m
-- This is the "functorial action" of the modality on morphisms.
-- Same uniform shape across all modality kinds.
/-- Reserved binder name for the `obj`-field's lambda argument. -/
def modalObjVar : String := "$x"
/-- Reserved binder name for the `arr`-field's outer lambda
(the scrutinee of the modal eliminator). -/
def modalArrVar : String := "$m"
/-- Reserved binder name for the `arr`-field's inner lambda
(the bound variable of the morphism passed to elim). -/
def modalArrInner : String := "$y"
/-- The modal functor, parameterised by `k : ModalityKind`. A single
endofunctor on `CType_as_Category ` realising any of the cohesion
triple's modalities by selecting the kind:
· `forModalityKind .flat` — the discrete reflection `♭`
· `forModalityKind .sharp` — the codiscrete coreflection `♯`
· `forModalityKind .shape` — the EML-localising shape `ʃ`
Replaces the Phase-1 trio (`flatFunctor` / `sharpFunctor` /
`shapeFunctor`), which were three syntactic copies of the same
construction differing only in which `ModalityKind` constructor
they instantiated. The construction is uniform in `k`: the
modality enters through the unified constructors `.modalIntro k`,
`.modalElim k`.
**Object map.** Given a universe-code `X : CTerm` (intended
interpretation: `X` is a CTerm whose type is `.univ ( := )` —
semantically, an encoded type), the modal image is
`λ$x. modalIntro k (X $x)`. This is the "code of the pointwise
M-modalised image" — a function that, when applied at any input,
wraps its result in the modality of kind `k`. Substantive in
both `X` and `k`: distinct Xs yield distinct lambda bodies;
distinct ks yield distinct `.modalIntro` heads.
**Morphism map.** Given a morphism `f : A → B` (a path-in-the-
universe, treated function-style as a CTerm), the modal image
is the function `M A → M B`:
`λ$m. modalElim k (λ$y. modalIntro k (f $y)) $m`
This is the standard "elim-then-intro" functorial action: take
the modal scrutinee `$m`, eliminate to get the underlying value,
apply `f`, and re-introduce under the same modality kind. The
body substantively mentions `f`, the source `X`, and the target
`Y` (through the elim discipline), as well as `k`.
**Functoriality witnesses.** Identity-preservation and
composition-preservation are reflexivity-paths in the universe
at the right-hand-side normal form of the functoriality
equation. The cubical evaluator reduces both endpoints to a
common normal form via the modal β-rule
(`eval_modalElim_beta`), and the path body is the corresponding
constant.
Per THEORY.md §3.1 / §3.3. -/
def forModalityKind ( : ULevel) (k : ModalityKind) :
CFunctor (CType_as_Category ) (CType_as_Category ) where
obj := fun X =>
-- λ$x. modalIntro k (X $x) — pointwise k-modalisation of the
-- code's fibre. Substantive in X (which appears as the head
-- of the inner application) and in k (which selects the
-- `.modalIntro` constructor).
.lam modalObjVar
(.modalIntro k (.app X (.var modalObjVar)))
arr := fun _X _Y f =>
-- λ$m. modalElim k (λ$y. modalIntro k (f $y)) $m
-- Functorial action: scrutinise the modal-input, apply f to the
-- underlying value, re-wrap. Substantive in both f and k.
.lam modalArrVar
(.modalElim k
(.lam modalArrInner
(.modalIntro k (.app f (.var modalArrInner))))
(.var modalArrVar))
preserves_id := fun _X =>
-- Path body: the constant path at the LHS of the functoriality
-- equation, which the cubical evaluator reduces to the RHS via
-- the modal β-rule `M.elim (M.intro a) = a` (Phase 1 axiom
-- `eval_modalElim_beta` instantiated at k). Reflexivity at this
-- normal form inhabits the documented Path.
.plam CCategory.lawDim
(.lam modalArrVar
(.modalElim k
(.lam modalArrInner
(.modalIntro k (.var modalArrInner)))
(.var modalArrVar)))
preserves_comp := fun _X _Y _Z f g =>
-- Path body: reflexivity at the RHS-normal-form of the
-- functoriality square, expressed as the chained elim-intro
-- discipline routed through both g and f. All three of f, g,
-- and the intermediate object Y substantively appear (via the
-- modal-elim discipline that exposes the chained applications).
.plam CCategory.lawDim
(.lam modalArrVar
(.modalElim k
(.lam modalArrInner
(.modalIntro k (.app g (.app f (.var modalArrInner)))))
(.var modalArrVar)))
-- ── §1a. Substantive-dependence rfl-lemmas + dependence theorems ─────────
-- The functor's `obj` and `arr` fields substantively mention their
-- inputs (so distinct inputs yield distinct outputs). These rfl-
-- lemmas pin down the encodings, parameterised over `k`.
/-- The modal functor's `obj` field encodes its argument inside a
lambda body — substantively `X`-dependent and `k`-dependent. -/
@[simp] theorem forModalityKind_obj ( : ULevel) (k : ModalityKind)
(X : CTerm) :
(forModalityKind k).obj X =
.lam modalObjVar (.modalIntro k (.app X (.var modalObjVar))) := rfl
/-- The modal functor's `arr` field encodes the morphism via the
elim/intro discipline — substantively `f`-dependent and
`k`-dependent. -/
@[simp] theorem forModalityKind_arr ( : ULevel) (k : ModalityKind)
(X Y f : CTerm) :
(forModalityKind k).arr X Y f =
.lam modalArrVar
(.modalElim k
(.lam modalArrInner
(.modalIntro k (.app f (.var modalArrInner))))
(.var modalArrVar)) := rfl
/-- The modal functor's `obj` is genuinely X-dependent: distinct X's
yield distinct lambda bodies (at any fixed `k`). -/
theorem forModalityKind_obj_dep ( : ULevel) (k : ModalityKind)
(X X' : CTerm) (h : X ≠ X') :
(forModalityKind k).obj X ≠ (forModalityKind k).obj X' := by
intro hEq
rw [forModalityKind_obj, forModalityKind_obj] at hEq
-- .lam x (.modalIntro k (.app X _)) = .lam x (.modalIntro k (.app X' _))
-- Peel through .lam, .modalIntro, .app to expose X vs X'.
have hbody := (CTerm.lam.injEq .. |>.mp hEq).2
have hmodal := (CTerm.modalIntro.injEq .. |>.mp hbody).2
have happ := (CTerm.app.injEq .. |>.mp hmodal).1
exact h happ
/-- The modal functor's `arr` is genuinely f-dependent (at any fixed
`k`). -/
theorem forModalityKind_arr_f_dep ( : ULevel) (k : ModalityKind)
(X Y f f' : CTerm) (h : f ≠ f') :
(forModalityKind k).arr X Y f ≠ (forModalityKind k).arr X Y f' := by
intro hEq
rw [forModalityKind_arr, forModalityKind_arr] at hEq
-- Peel: .lam $m (.modalElim k (.lam $y (.modalIntro k (.app f $y))) $m)
-- through the outer lam, the modalElim, the inner lam, the modalIntro,
-- the app — exposing f vs f' as the LHS of the inner .app.
have hbody := (CTerm.lam.injEq .. |>.mp hEq).2
have hflatArg := (CTerm.modalElim.injEq .. |>.mp hbody).2.1
have hLam := (CTerm.lam.injEq .. |>.mp hflatArg).2
have hIntro := (CTerm.modalIntro.injEq .. |>.mp hLam).2
have happ := (CTerm.app.injEq .. |>.mp hIntro).1
exact h happ
-- ── §2. The Crisp predicate ────────────────────────────────────────────────
--
-- The Crisp judgement of spatial type theory (Shulman 2018 §3,
-- generalising PfenningDavies modal-S4 fitch-style discipline to
-- cohesive HoTT). A CTerm is *crisp* when it is introduced via a
-- modal elimination — semantically, it is a value extracted from a
-- modalised type and is therefore safe to re-introduce under any
-- further modal-introduction.
--
-- Refactor Phase 3: the inductive constructors are parameterised
-- over `k : ModalityKind` rather than restricted to `.flat`. Every
-- modal eliminator (any of `♭`, `♯`, `ʃ`) extracts a value from a
-- modalised subuniverse, and that value is crisp by construction.
-- The `flat`-restricted prior form was a Phase-1 specialisation that
-- the unified `ModalityKind` syntax now subsumes — the predicate's
-- introduction discipline is uniform across the cohesion triple.
--
-- This phase delivers the term-level Crisp predicate. The companion
-- spec piece — the *context-level* refinement `CContext.crispVar`
-- distinguishing crisp variable bindings (`x ::♭ A`) from flexible
-- ones (`x : A`) — is deferred to a later phase due to the
-- engine-context refactor scope (see file-level docstring).
--
-- Inductive constructors:
-- · `modalElimBody k f m` — a `modalElim k f m` term is crisp at
-- any kind k. The classic spatial-TT rule generalised across
-- modalities: every modal eliminator extracts a value from the
-- M-modalised subuniverse, and that value is crisp. This is
-- the head case.
-- · `modalIntroOfCrisp k h` — `modalIntro k a` is crisp when `a`
-- is crisp. Closure under further modal introduction at any
-- kind: a crisp value can be re-wrapped under the same or any
-- other modality without losing crispness. This makes Crisp
-- closed under the modal idempotency cycle.
-- · `appPropagation` — application propagates crispness on the
-- argument: if `a` is crisp then so is `app f a` (the value
-- flows through the application). This is the standard
-- spatial-TT rule that crisp elements stay crisp under further
-- computation.
/-- The Crisp judgement (THEORY.md §3.2 / Shulman 2018 §3): a
CTerm-level predicate carving out the crisp values — those
introduced via a modal elimination, possibly re-wrapped or
applied.
Refactor Phase 3: the constructors are parameterised over
`k : ModalityKind` rather than restricted to `.flat`. The
spatial-TT discipline is uniform across the cohesion triple
`♭`/`♯`/`ʃ`: every modal eliminator extracts a value from a
modalised subuniverse and that value is crisp by construction.
Constructors:
· `modalElimBody k f m` — the head case at any kind: every
`modalElim k f m` term is crisp. This is the spatial-TT
introduction rule for crispness, generalised across the
modality triple — `M.elim` extracts a value from the
M-modalised subuniverse (discrete for `♭`, codiscrete for
`♯`, shape-localised for `ʃ`), and the result is crisp by
construction.
· `modalIntroOfCrisp k a` (with `Crisp a` premise) — closure
under modal re-introduction at any kind: a crisp `a`
re-wrapped as `modalIntro k a` remains crisp. This
realises the modal idempotency cycle `M ∘ M = M` at the
predicate level, uniformly across the modality triple.
· `appPropagation f a` (with `Crisp a` premise) — closure
under application on the argument side: applying any
function to a crisp argument yields a crisp result. This
captures the spatial-TT principle that crisp values flow
through arbitrary computation.
**Deferred:** the context-side refinement `CContext.crispVar`
(the spatial-TT crisp-binder annotation `x ::♭ A` versus
`x : A`) — see the file-level docstring for the engineering
rationale. Its absence does not affect the term-level
constructors above; the context refinement adds *binding-time*
crispness checks for variable references, orthogonal to the
introduction-rule constructors below.
Reference: Shulman 2018 (arXiv:1509.07584) §3 "Spatial type
theory"; LicataShulmanRiley 2017 (arXiv:1706.07526) §6. -/
inductive Crisp : CTerm → Prop where
/-- Head rule: every `modalElim k f m` term is crisp by
introduction, at any modality kind. -/
| modalElimBody (k : ModalityKind) (f m : CTerm) :
Crisp (CTerm.modalElim k f m)
/-- Closure under modal re-introduction: a crisp argument inside
`modalIntro k a` stays crisp, at any modality kind. -/
| modalIntroOfCrisp (k : ModalityKind) {a : CTerm} (h : Crisp a) :
Crisp (CTerm.modalIntro k a)
/-- Propagation through application: applying any function to a
crisp argument yields a crisp result. -/
| appPropagation {f a : CTerm} (h : Crisp a) :
Crisp (CTerm.app f a)
/-- Convenience constructor: a bare `modalElim k f m` is crisp. Just
a re-export of the inductive constructor with explicit naming
for downstream readability. -/
theorem Crisp.of_modalElim (k : ModalityKind) (f m : CTerm) :
Crisp (CTerm.modalElim k f m) :=
Crisp.modalElimBody k f m
/-- Substantive content: a *non-modalElim, non-modalIntro, non-app*
head — for instance, a bare variable — is not in the head case.
This pins down that `Crisp` is *not* trivially total: the
inductive does not have a constructor for `var`, so a `var x`
cannot be crisp via `modalElimBody`, `modalIntroOfCrisp`, or
`appPropagation`'s direct shape — the `var` head distinguishes
it from each of those CTerm shapes via constructor disjointness.
This rules out the `Crisp _ := True` failure mode. -/
theorem Crisp.var_not_immediate (x : String) :
¬ ∃ (k : ModalityKind) (f m : CTerm),
CTerm.var x = CTerm.modalElim k f m := by
rintro ⟨k, f, m, h⟩
cases h
-- ── §2a. Unit and counit underlying CTerms ─────────────────────────────────
--
-- The two adjunctions of the cohesive triple `ʃ ⊣ ♭ ⊣ ♯` are
-- `♭ ⊣ ♯` and `ʃ ⊣ ♭`. Each adjunction comes with a unit and a
-- counit natural transformation. The component at each object/type
-- has an *underlying function* (the action on elements / on the
-- `apply`-image) plus a *naturality witness* (a path-equality
-- propagating the modal β/η-rules).
--
-- This section delivers the underlying functions as concrete CTerms
-- built directly from the unified modal constructors `.modalIntro k`
-- and `.modalElim k`. No placeholder variables; each definition
-- mentions both the `.flat`/`.sharp`/`.shape` `ModalityKind` constants
-- and uses the proper modal introduction/elimination discipline.
--
-- The naturality witnesses (path-equalities) live in §3, and depend
-- on the modal Path-equality lift hypothesis FS-H18 (see
-- `topolei/docs/HYPOTHESES.md`). This section's CTerms are
-- substantive — they are real Lean defs that downstream code can
-- already reference, rather than abstract `Nonempty`-existentials.
--
-- ── Reserved binder names ────────────────────────────────────────────────────
-- We use distinct binder names for the unit (input element) and the
-- counit's nested elims (each of which has its own bound variable).
-- These are reserved with a `$` prefix to avoid collision with
-- user-supplied CTerm variable names (matching the convention used
-- for `modalObjVar`, `modalArrVar`, `modalArrInner` above).
/-- Reserved binder name for the input of a unit's underlying lambda
(the element of `A` being mapped under `η`). -/
def modalUnitVar : String := "$a"
/-- Reserved binder name for the input of a counit's outer lambda
(the modal scrutinee being eliminated). -/
def modalCounitVar : String := "$x"
/-- Reserved binder name for the inner-elim's bound variable in a
counit (the value extracted from the outer modal layer). -/
def modalCounitInner : String := "$y"
/-- Reserved binder name for the innermost-elim's bound variable in a
counit (the underlying element of the doubly-modalised value). -/
def modalCounitCore : String := "$z"
/-- Underlying function of the **unit** of `♭ ⊣ ♯` at type `A`:
a CTerm representing `η_A : A → ♯ (♭ A)`.
Body: `λ$a. modalIntro .sharp (modalIntro .flat $a)`.
Reading: take the input element `$a : A`; introduce it under
`♭` to get a value of `♭ A`; introduce *that* under `♯` to
get a value of `♯ (♭ A)`. This is the standard discrete-then-
codiscrete inclusion that realises the unit of the flat-sharp
adjunction at the type level.
Substantive in `A` (via the type-checked discipline:
`flatSharpUnit_typed` records that this CTerm has type
`pi $a A (modal .sharp (modal .flat A))`); substantive in the
`.flat` and `.sharp` `ModalityKind` constants (they appear
syntactically as the modal-intro head constants).
Note on the `( : ULevel) (A : CType )` signature: the body
is *level-uniform* — the underlying CTerm does not actually
mention `` or `A` syntactically, since CTerm is un-indexed by
universe level (Syntax.lean §3 design rationale). The
`(, A)` arguments scope the typed-correctness theorem
`flatSharpUnit_typed`, which *does* mention them. -/
def flatSharpUnit ( : ULevel) (A : CType ) : CTerm :=
let _ := ; let _ := A -- arguments scope the typed theorem
.lam modalUnitVar
(.modalIntro .sharp (.modalIntro .flat (.var modalUnitVar)))
/-- Underlying function of the **counit** of `♭ ⊣ ♯` at type `A`:
a CTerm representing `ε_A : ♭ (♯ A) → A`.
Body:
`λ$x. modalElim .flat (λ$y. modalElim .sharp (λ$z. $z) $y) $x`.
Reading: take the input scrutinee `$x : ♭ (♯ A)`. Eliminate
under `♭` with the eliminator function
`λ$y. modalElim .sharp (λ$z. $z) $y`, which itself eliminates
its input `$y : ♯ A` under `♯` with the identity eliminator
`λ$z. $z`, returning the underlying value `$z : A`. The chained
`modalElim .flat` then `modalElim .sharp` discipline strips off
both modal layers, yielding a value in `A`.
Substantive in the `.flat` and `.sharp` `ModalityKind` constants;
typed-correctness recorded by `flatSharpCounit_typed`. -/
def flatSharpCounit ( : ULevel) (A : CType ) : CTerm :=
let _ := ; let _ := A
.lam modalCounitVar
(.modalElim .flat
(.lam modalCounitInner
(.modalElim .sharp
(.lam modalCounitCore (.var modalCounitCore))
(.var modalCounitInner)))
(.var modalCounitVar))
/-- Underlying function of the **unit** of `ʃ ⊣ ♭` at type `A`:
a CTerm representing `η_A : A → ♭ (ʃ A)`.
Body: `λ$a. modalIntro .flat (modalIntro .shape $a)`.
Reading: take the input element `$a : A`; introduce it under
`ʃ` to get a value of `ʃ A`; introduce *that* under `♭` to
get a value of `♭ (ʃ A)`. This is the shape-then-discrete
inclusion realising the unit of the shape-flat adjunction.
Typed-correctness recorded by `shapeFlatUnit_typed`. -/
def shapeFlatUnit ( : ULevel) (A : CType ) : CTerm :=
let _ := ; let _ := A
.lam modalUnitVar
(.modalIntro .flat (.modalIntro .shape (.var modalUnitVar)))
/-- Underlying function of the **counit** of `ʃ ⊣ ♭` at type `A`:
a CTerm representing `ε_A : ʃ (♭ A) → A`.
Body:
`λ$x. modalElim .shape (λ$y. modalElim .flat (λ$z. $z) $y) $x`.
Reading: input scrutinee `$x : ʃ (♭ A)`. Eliminate under
`ʃ` with the eliminator function
`λ$y. modalElim .flat (λ$z. $z) $y`, which eliminates
`$y : ♭ A` under `♭` with the identity eliminator,
yielding the underlying `$z : A`. Chained `modalElim .shape`
then `modalElim .flat` strips both modal layers.
Typed-correctness recorded by `shapeFlatCounit_typed`. -/
def shapeFlatCounit ( : ULevel) (A : CType ) : CTerm :=
let _ := ; let _ := A
.lam modalCounitVar
(.modalElim .shape
(.lam modalCounitInner
(.modalElim .flat
(.lam modalCounitCore (.var modalCounitCore))
(.var modalCounitInner)))
(.var modalCounitVar))
-- ── §2a-rfl. Rfl-lemmas pinning the body of each unit/counit ───────────────
-- These witness that the bodies are exactly what their docstrings
-- promise — distinct binder names, the proper modal-intro/elim
-- nesting. Used in §2b for typed-correctness proofs and in
-- `forModalityKind_*_dep`-style dependence theorems.
/-- The flat-sharp unit's body unfolds to its documented lambda. -/
@[simp] theorem flatSharpUnit_eq ( : ULevel) (A : CType ) :
flatSharpUnit A =
.lam modalUnitVar
(.modalIntro .sharp (.modalIntro .flat (.var modalUnitVar))) := rfl
/-- The flat-sharp counit's body unfolds to its documented lambda. -/
@[simp] theorem flatSharpCounit_eq ( : ULevel) (A : CType ) :
flatSharpCounit A =
.lam modalCounitVar
(.modalElim .flat
(.lam modalCounitInner
(.modalElim .sharp
(.lam modalCounitCore (.var modalCounitCore))
(.var modalCounitInner)))
(.var modalCounitVar)) := rfl
/-- The shape-flat unit's body unfolds to its documented lambda. -/
@[simp] theorem shapeFlatUnit_eq ( : ULevel) (A : CType ) :
shapeFlatUnit A =
.lam modalUnitVar
(.modalIntro .flat (.modalIntro .shape (.var modalUnitVar))) := rfl
/-- The shape-flat counit's body unfolds to its documented lambda. -/
@[simp] theorem shapeFlatCounit_eq ( : ULevel) (A : CType ) :
shapeFlatCounit A =
.lam modalCounitVar
(.modalElim .shape
(.lam modalCounitInner
(.modalElim .flat
(.lam modalCounitCore (.var modalCounitCore))
(.var modalCounitInner)))
(.var modalCounitVar)) := rfl
-- ── §2b. Constructive partial discharges (typed-correctness) ───────────────
--
-- The unit/counit CTerms above have intended Π-types that record the
-- "function at the type level" interpretation of each:
--
-- flatSharpUnit A : A → ♯ (♭ A)
-- flatSharpCounit A : ♭ (♯ A) → A
-- shapeFlatUnit A : A → ♭ (ʃ A)
-- shapeFlatCounit A : ʃ (♭ A) → A
--
-- These typings are dischargeable *now* — they require only the
-- existing `HasType.lam` / `HasType.var` / `HasType.modalIntro` /
-- `HasType.modalElim` / `HasType.app` rules (Typing.lean) and do
-- not depend on any Path-equality lift. They are the
-- "constructive partial discharge" that the user values: real
-- progress on the adjunction content that requires nothing beyond
-- already-landed engine machinery.
--
-- By contrast, the *naturality* squares and *triangle identities*
-- (which sit inside the `CAdjoint` and `CNatTrans` structures of
-- §3) are Path-equality content — they need FS-H18 to discharge.
-- The split between this §2b and §3 is therefore the precise
-- "what we can prove now / what waits on FS-H18" boundary.
/-- Reserved Π-binder name for the unit's intended Π-type signature.
Mirrors the binder name used in the unit's CTerm body (so that
substitution would be well-defined under the dependent-Π
interpretation, were the codomain to depend on the binder). -/
def unitTypeBinder : String := modalUnitVar
/-- Reserved Π-binder name for the counit's intended Π-type
signature. Same convention as `unitTypeBinder`. -/
def counitTypeBinder : String := modalCounitVar
/-- **Typed correctness of `flatSharpUnit`.** The CTerm `flatSharpUnit
A` has the Π-type `A → ♯ (♭ A)` in the empty context.
Discharge: by `HasType.lam` followed by `HasType.modalIntro`
twice (once for `.sharp`, once for `.flat`) and `HasType.var`
at the inner-most reference. This is a real Lean proof — no
sorry, no axiom, no Path-equality lift.
Substantive constructive content. The Π-type makes the
"underlying function" claim of the unit precise: `flatSharpUnit
A` is genuinely a function CTerm of the right type at A. -/
theorem flatSharpUnit_typed ( : ULevel) (A : CType ) :
HasType []
(flatSharpUnit A)
(.pi unitTypeBinder A (.modal .sharp (.modal .flat A))) := by
rw [flatSharpUnit_eq]
-- Goal: HasType [] (.lam $a (.modalIntro .sharp (.modalIntro .flat (.var $a))))
-- (.pi $a A (.modal .sharp (.modal .flat A)))
apply HasType.lam
-- Goal: HasType [($a, ⟨ℓ, A⟩)] (.modalIntro .sharp (.modalIntro .flat (.var $a)))
-- (.modal .sharp (.modal .flat A))
apply HasType.modalIntro
-- Goal: HasType [($a, ⟨ℓ, A⟩)] (.modalIntro .flat (.var $a)) (.modal .flat A)
apply HasType.modalIntro
-- Goal: HasType [($a, ⟨ℓ, A⟩)] (.var $a) A
exact HasType.var (List.mem_cons_self ..)
/-- **Typed correctness of `flatSharpCounit`.** The CTerm
`flatSharpCounit A` has the Π-type `♭ (♯ A) → A` in the empty
context.
Discharge: outer `HasType.lam`, then `HasType.modalElim` (with
eliminator-function-typed-as-`(♯ A) → A` and scrutinee-typed-as-
`♭ (♯ A)`), recursing into the inner elim with the same
discipline at `.sharp`. The innermost identity lambda
`λ$z. $z` discharges via `HasType.lam` + `HasType.var`. -/
theorem flatSharpCounit_typed ( : ULevel) (A : CType ) :
HasType []
(flatSharpCounit A)
(.pi counitTypeBinder (.modal .flat (.modal .sharp A)) A) := by
rw [flatSharpCounit_eq]
apply HasType.lam
-- Context now: [($x, ⟨ℓ, .modal .flat (.modal .sharp A)⟩)]
-- Goal: the inner elim has type A.
-- HasType.modalElim asks for:
-- f : pi var (.modal .sharp A) A (the eliminator function)
-- m : .modal .flat (.modal .sharp A) (the scrutinee)
refine HasType.modalElim
(var := modalCounitCore)
(A := .modal .sharp A)
(C := A)
(k := .flat)
?_ -- f : pi $z (.modal .sharp A) A
?_ -- m : .modal .flat (.modal .sharp A)
· -- Inner eliminator: λ$y. modalElim .sharp (λ$z. $z) $y
-- needs HasType (..ctx..) (.lam $y (...)) (.pi $z (.modal .sharp A) A).
apply HasType.lam
-- ctx : [($y, ⟨ℓ, .modal .sharp A⟩), ($x, ⟨ℓ, .modal .flat (.modal .sharp A)⟩)]
-- Goal: HasType ctx (.modalElim .sharp (.lam $z (.var $z)) (.var $y)) A
refine HasType.modalElim
(var := modalCounitCore)
(A := A)
(C := A)
(k := .sharp)
?_ -- f' : pi $z A A (the identity)
?_ -- m' : .modal .sharp A (the inner scrutinee)
· -- Identity lambda: λ$z. $z
apply HasType.lam
-- ctx2 : [($z, ⟨ℓ, A⟩), ($y, ⟨ℓ, .modal .sharp A⟩),
-- ($x, ⟨ℓ, .modal .flat (.modal .sharp A)⟩)]
-- Goal: HasType ctx2 (.var $z) A
exact HasType.var (List.mem_cons_self ..)
· -- Inner scrutinee: var $y at type .modal .sharp A
-- ctx : [($y, ⟨ℓ, .modal .sharp A⟩),
-- ($x, ⟨ℓ, .modal .flat (.modal .sharp A)⟩)]
exact HasType.var (List.mem_cons_self ..)
· -- Outer scrutinee: var $x at type .modal .flat (.modal .sharp A)
exact HasType.var (List.mem_cons_self ..)
/-- **Typed correctness of `shapeFlatUnit`.** The CTerm
`shapeFlatUnit A` has the Π-type `A → ♭ (ʃ A)` in the empty
context. -/
theorem shapeFlatUnit_typed ( : ULevel) (A : CType ) :
HasType []
(shapeFlatUnit A)
(.pi unitTypeBinder A (.modal .flat (.modal .shape A))) := by
rw [shapeFlatUnit_eq]
apply HasType.lam
apply HasType.modalIntro
apply HasType.modalIntro
exact HasType.var (List.mem_cons_self ..)
/-- **Typed correctness of `shapeFlatCounit`.** The CTerm
`shapeFlatCounit A` has the Π-type `ʃ (♭ A) → A` in the empty
context. -/
theorem shapeFlatCounit_typed ( : ULevel) (A : CType ) :
HasType []
(shapeFlatCounit A)
(.pi counitTypeBinder (.modal .shape (.modal .flat A)) A) := by
rw [shapeFlatCounit_eq]
apply HasType.lam
refine HasType.modalElim
(var := modalCounitCore)
(A := .modal .flat A)
(C := A)
(k := .shape)
?_
?_
· apply HasType.lam
refine HasType.modalElim
(var := modalCounitCore)
(A := A)
(C := A)
(k := .flat)
?_
?_
· apply HasType.lam
exact HasType.var (List.mem_cons_self ..)
· exact HasType.var (List.mem_cons_self ..)
· exact HasType.var (List.mem_cons_self ..)
-- ── §2b-dep. Substantive non-vacuity / non-degeneracy theorems ─────────────
-- The unit/counit CTerms above are *not* trivial wrappers — distinct
-- binder names (unit-binder vs counit-binder) ensure each is
-- syntactically distinguishable at the head, and the modality kinds
-- appear inside the term so that swapping any one of them produces
-- a syntactically distinct CTerm.
/-- The flat-sharp unit and flat-sharp counit are syntactically
distinct — the unit's head is a `modalIntro`, the counit's head
body has a `modalElim` immediately under the outer lambda. This
rules out the degenerate failure mode where unit and counit
collapse to the same CTerm. -/
theorem flatSharpUnit_ne_Counit ( : ULevel) (A : CType ) :
flatSharpUnit A ≠ flatSharpCounit A := by
rw [flatSharpUnit_eq, flatSharpCounit_eq]
-- LHS: .lam $a (.modalIntro .sharp ...)
-- RHS: .lam $x (.modalElim .flat ...)
-- Lambda binder names differ ($a vs $x), and bodies have different
-- head constructors. Lambda injectivity exposes either disagreement.
intro hEq
have hbinder := (CTerm.lam.injEq .. |>.mp hEq).1
-- $a = $x contradicts our binder convention
exact (by decide : modalUnitVar ≠ modalCounitVar) hbinder
/-- The shape-flat unit and shape-flat counit are syntactically
distinct. Same shape as `flatSharpUnit_ne_Counit`. -/
theorem shapeFlatUnit_ne_Counit ( : ULevel) (A : CType ) :
shapeFlatUnit A ≠ shapeFlatCounit A := by
rw [shapeFlatUnit_eq, shapeFlatCounit_eq]
intro hEq
have hbinder := (CTerm.lam.injEq .. |>.mp hEq).1
exact (by decide : modalUnitVar ≠ modalCounitVar) hbinder
/-- The flat-sharp unit and the shape-flat unit are syntactically
distinct — the inner `modalIntro`s carry different `ModalityKind`
constants (`.flat` / `.sharp` for the FS-unit, `.shape` /
`.flat` for the SF-unit). Distinct kinds ⇒ distinct CTerms.
This rules out the failure mode where the two adjunction
units accidentally coincide. -/
theorem flatSharpUnit_ne_shapeFlatUnit ( : ULevel) (A : CType ) :
flatSharpUnit A ≠ shapeFlatUnit A := by
rw [flatSharpUnit_eq, shapeFlatUnit_eq]
-- LHS: .lam $a (.modalIntro .sharp (.modalIntro .flat (.var $a)))
-- RHS: .lam $a (.modalIntro .flat (.modalIntro .shape (.var $a)))
-- The outermost modalIntro's kind differs: .sharp vs .flat.
intro hEq
have hbody := (CTerm.lam.injEq .. |>.mp hEq).2
have hkind := (CTerm.modalIntro.injEq .. |>.mp hbody).1
-- hkind : ModalityKind.sharp = ModalityKind.flat
exact (by decide : (ModalityKind.sharp : ModalityKind) ≠ .flat) hkind
/-- The flat-sharp counit and the shape-flat counit are syntactically
distinct — the outermost `modalElim` carries different kinds. -/
theorem flatSharpCounit_ne_shapeFlatCounit ( : ULevel) (A : CType ) :
flatSharpCounit A ≠ shapeFlatCounit A := by
rw [flatSharpCounit_eq, shapeFlatCounit_eq]
intro hEq
have hbody := (CTerm.lam.injEq .. |>.mp hEq).2
have hkind := (CTerm.modalElim.injEq .. |>.mp hbody).1
exact (by decide : (ModalityKind.flat : ModalityKind) ≠ .shape) hkind
-- ── §3. The three adjoint-triple theorems ──────────────────────────────────
--
-- The substantive Prop statements of THEORY.md §3.3, restated using
-- the unified `forModalityKind`. Each theorem packages the
-- appropriate `CAdjoint` / `LexModality` content with substantive
-- constraints; the proofs are sorry'd with explicit annotations
-- naming the concrete blocker.
/-- **Theorem `flat_sharp_adjoint`** (THEORY.md §3.3): the flat
modality is left adjoint to the sharp modality, viewed as
endofunctors on the universe-as-category at level ``.
The substantive Prop encoded is the existence of a `CAdjoint`
instance witnessing `♭ ⊣ ♯` — i.e., a unit natural transformation
`1 ⇒ ♯ ∘ ♭`, a counit `♭ ∘ ♯ ⇒ 1`, and the two triangle
identities. The CAdjoint structure (Category.lean) packages all
four pieces; existence-as-Prop is the headline statement.
Phase 3 form: both functors are obtained from the unified
`forModalityKind ` by selecting `.flat` and `.sharp`.
**Concrete progress (no FS-H18).** The unit/counit's *underlying
function* CTerms are landed in §2a — `flatSharpUnit` and
`flatSharpCounit` — with substantive bodies built from the
unified modal constructors and typed-correctness theorems
`flatSharpUnit_typed` / `flatSharpCounit_typed` (§2b) showing
they have the proper Π-type. The remaining gap is the
natural-transformation packaging, which requires path-equality.
**Specific blocker: FS-H18 (modal Path-equality lift).**
The naturality squares and triangle identities require the modal
β-rule (`eval_modalElim_beta` from `Eval.lean`, itself FS-H15)
lifted from the eval-equation level to a Path-equality at the
universe level. Once FS-H18 lands (see
`topolei/docs/HYPOTHESES.md`), the `CAdjoint` instance
constructs as:
unit.comp X := plam ∘ flatSharpUnit-action-at-X
counit.comp X := plam ∘ flatSharpCounit-action-at-X
triangle1 / 2 := plam (β_path .flat) ∘ plam (β_path .sharp)
where `β_path k` is the FS-H18 Path-form of the eval-level β. -/
theorem flat_sharp_adjoint ( : ULevel) :
Nonempty (CAdjoint (forModalityKind .flat) (forModalityKind .sharp)) := by
-- waits on: FS-H18 (modal Path-equality lift, see
-- topolei/docs/HYPOTHESES.md). Once FS-H18 lands, the CAdjoint
-- instance is constructed from the §2a underlying CTerms
-- `flatSharpUnit` / `flatSharpCounit` (whose typed-correctness is
-- already discharged by `flatSharpUnit_typed` /
-- `flatSharpCounit_typed` in §2b) plus the triangle identities,
-- which are precisely the FS-H18 Path-form of the modal β-rule
-- at `.flat` and `.sharp`. No additional axioms are needed.
sorry
/-- **Theorem `shape_flat_adjoint`** (THEORY.md §3.3): the shape
modality is left adjoint to the flat modality.
Same packaging as `flat_sharp_adjoint`: existence of a
`CAdjoint` instance for `ʃ ⊣ ♭` viewed as endofunctors on
`CType_as_Category `, both obtained from the unified
`forModalityKind ` at `.shape` and `.flat`.
**Concrete progress (no FS-H18).** The unit/counit's
underlying function CTerms are landed in §2a as `shapeFlatUnit`
and `shapeFlatCounit`, both with substantive bodies and
typed-correctness theorems (§2b: `shapeFlatUnit_typed` /
`shapeFlatCounit_typed`).
**Specific blocker: FS-H18 (modal Path-equality lift)** —
same hypothesis as `flat_sharp_adjoint`, this time instantiated
at the `.shape` and `.flat` modality kinds. Once FS-H18 lands,
the `CAdjoint` instance constructs from the §2a CTerms
analogously to `flat_sharp_adjoint`'s discharge route. -/
theorem shape_flat_adjoint ( : ULevel) :
Nonempty (CAdjoint (forModalityKind .shape) (forModalityKind .flat)) := by
-- waits on: FS-H18 (modal Path-equality lift, see
-- topolei/docs/HYPOTHESES.md), instantiated at `.shape` and
-- `.flat`. The §2a underlying-function CTerms `shapeFlatUnit` /
-- `shapeFlatCounit` (typed-correctness in §2b) provide the
-- naturality components; the triangle identities are FS-H18 at
-- the `.shape` / `.flat` kinds. No additional axioms.
sorry
/-- **Theorem `cohesive_triple`** (THEORY.md §3.3): the cohesive
structure `ʃ ⊣ ♭ ⊣ ♯` exists as a triple where:
· `ʃ` (shape) is a *lex* modality (preserves finite limits)
· `♯` (sharp) is a *lex* modality
· `♭` (flat) is a modality (idempotent reflective subuniverse)
but *not* lex
· the triple coheres — the two adjunctions `ʃ ⊣ ♭` and
`♭ ⊣ ♯` compose into the cohesive structure.
The substantive Prop encoded packages all three pieces:
1. a lex-modality witness for shape;
2. a lex-modality witness for sharp;
3. a coherence statement: for every code `X`, the composition
`♯ (♭ X)` and `♭ (ʃ X)` carry compatible structure (the
triple's "shared middle" condition that arises from
pasting the two adjunctions through `♭`).
Phase 3 form: the lex-modality apply-fields and the coherence
witnesses are stated using the unified `.modal k` constructor
and `forModalityKind` directly.
Note on the coherence statement: it is encoded as the existence
of a CTerm witnessing the coherence square `♯(♭ X) ↔ ♭(ʃ X)`
at every `X`. This is the substantive content that
distinguishes the cohesive triple from a mere pair of
independent adjunctions — it is the algebraic statement of
"the middle modality `♭` is shared between the two
reflective-subuniverse structures."
**Concrete progress (no FS-H18).** The coherence-witness
*function-shape* CTerms `flatSharpUnit/Counit` and
`shapeFlatUnit/Counit` (§2a) already provide the building
blocks of the coherence square: pasting the unit of `♭ ⊣ ♯`
with the counit of `ʃ ⊣ ♭` (composed appropriately) yields
the algebraic translation between `♯(♭ X)` and `♭(ʃ X)` at
the function level.
**Specific blocker: FS-H18** for the lex-modality witnesses
of `ʃ` and `♯` (preserves_pullbacks / preserves_terminal as
Path-equalities), and for the coherence square's Path-form. -/
theorem cohesive_triple ( : ULevel) :
-- (1) shape is lex
(∃ shapeLex : LexModality ,
shapeLex.toModality.apply = fun A => CType.modal .shape A) ∧
-- (2) sharp is lex
(∃ sharpLex : LexModality ,
sharpLex.toModality.apply = fun A => CType.modal .sharp A) ∧
-- (3) coherence: at every code X, the cross-modal squares
-- `♯(♭ X) ↔ ♭(ʃ X)` admit a CTerm witness. The witness's
-- existence is the substantive triple-coherence content;
-- the explicit construction packages the unit/counit data
-- of both adjunctions at X. Substantive in X — distinct
-- X's yield distinct coherence-witness CTerms (each
-- mentions X via the chained obj-field lambdas of
-- `forModalityKind` at `.flat` / `.sharp` / `.shape`).
(∀ X : CTerm,
∃ coh : CTerm,
coh = (forModalityKind .sharp).obj
((forModalityKind .flat).obj X)
coh = (forModalityKind .flat).obj
((forModalityKind .shape).obj X)) := by
-- waits on: FS-H18 (modal Path-equality lift, see
-- topolei/docs/HYPOTHESES.md), at all three of `.flat` / `.sharp` /
-- `.shape`. Discharge route: combine the §2a underlying-function
-- CTerms (flatSharpUnit/Counit, shapeFlatUnit/Counit) with the
-- FS-H18 Path-form to get the lex-modality witnesses
-- (`preserves_pullbacks` and `preserves_terminal` as Path-
-- equalities on the universe-as-category) plus the coherence
-- square `♯(♭ X) ↔ ♭(ʃ X)` as the pasted unit/counit data of
-- the two §3 adjunctions. The lex extension itself additionally
-- depends on the pullback machinery in `Category.lean`
-- (`CCategory_internal` `sorry`-cluster), which is orthogonal
-- to FS-H18.
sorry
-- ── §4. Soundness theorem for the modal β-rule ─────────────────────────────
--
-- Phase 1 added the unified eval β-axiom (`eval_modalElim_beta` in
-- `Eval.lean`) that asserts the reduction equation at the value
-- level, parameterised by `k : ModalityKind`. This phase records
-- the corresponding Eq fact at the theorem level so downstream
-- tactics (rewriting, simp) can fire on it.
--
-- Refactor Phase 3: the prior trio of `flat_beta_sound` /
-- `sharp_beta_sound` / `shape_beta_sound` collapses into a single
-- `modal_beta_sound` parameterised over `k`. Each was a
-- definitional copy of the same axiom instantiated at distinct
-- `ModalityKind` cases; the unified statement is one theorem.
--
-- The body is an immediate application of the Phase 1 axiom — no
-- further content is needed. The axiom is a propositional equality,
-- not definitional, because `eval` is `partial` (the modal arms of
-- `eval` are `match` on the evaluated scrutinee, which the Lean
-- kernel cannot reduce definitionally for `partial` defs). Hence
-- `rfl` does not close the goal, but the axiom does.
/-- **Soundness for the modal β-rule** (THEORY.md §3.2 reduction
rules), unified across the modality triple.
The reduction
`modalElim k f (modalIntro k a) → vApp (eval f) (eval a)`
holds at the eval-equation level, at any `k : ModalityKind`.
Recorded here as a theorem so downstream tactics may rewrite
with it. The underlying axiom is the unified
`eval_modalElim_beta` from `Eval.lean`.
Refactor Phase 3: replaces the prior trio (`flat_beta_sound` /
`sharp_beta_sound` / `shape_beta_sound`) with a single
`ModalityKind`-parameterised statement. -/
theorem modal_beta_sound (env : CEnv) (k : ModalityKind) (f a : CTerm) :
eval env (.modalElim k f (.modalIntro k a)) =
vApp (eval env f) (eval env a) :=
eval_modalElim_beta env k f a
end CubicalTransport.Modal