Some checks are pending
Lean Action CI / build (push) Waiting to run
Lands the foundational DecidableEq machinery and the @[simp]-
based question-form routing in one go (per project discipline:
no shortcuts, no compat shims).
CubicalTransport/DecEq.lean (new, ~290 lines):
- Mutual decEq for the 5-way AST block (CType, CTerm, CTypeArg,
CtorSpec, CTypeSchema) plus list/clause/branch helpers
(decEqListCType, decEqListCTerm, decEqListCTypeArg,
decEqListCtorSpec, decEqClauses, decEqBranches).
- Returns Decidable (a = b) directly; uses OR-patterns for
cross-constructor mismatches, discharged uniformly via cases.
- Five DecidableEq instances declared post-block.
- Lean 4 deriving doesn't support mutual inductives; manual
decEq is the canonical approach.
CubicalTransport/Interval.lean: deriving DecidableEq on DimExpr.
CubicalTransport/Face.lean: deriving DecidableEq on FaceFormula.
CubicalTransport/Question.lean:
- All 11 classifier Decidable instances now land:
IsConstLine, IsFullFace, IsEmptyFace, IsTransport,
IsIntervalLine, IsUnivLine — direct from DecidableEq.
IsPathLine, IsPiLine, IsSigmaLine, IsGlueLine, IsIndLine —
via match h : q.body with on the head constructor +
existential-witness reconstruction in the isTrue arm.
- @[simp] tags on ask_of_full_face / ask_of_empty_face /
ask_of_const_line / ask_of_transport_full_face — the Level 2
routing through CompQ.Equiv.
- Three example proofs at end of file demonstrating that the
simp-set composes (full-face C1, empty-face C2, transport-
shaped interval-line reduction).
CubicalTransport/FFITest.lean: 6 new classifier-decidability
smoke tests (IsFullFace, IsTransport×2, IsPiLine, IsIntervalLine).
Test count: 84 → 89 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
399 lines
22 KiB
Text
399 lines
22 KiB
Text
/-
|
||
CubicalTransport.DecEq
|
||
======================
|
||
Decidable equality for the 5-way mutual block (`CType`, `CTerm`,
|
||
`CTypeArg`, `CtorSpec`, `CTypeSchema`) plus the list/pair helper
|
||
shapes that appear inside it.
|
||
|
||
Lean 4's `deriving instance DecidableEq` does not currently support
|
||
mutual inductives — has to be written manually. The mutual `decEq`
|
||
block returns `Decidable (a = b)` directly; instances are then
|
||
declared post-hoc.
|
||
|
||
Imports `CubicalTransport.Syntax` and depends on the `DecidableEq`
|
||
instances for `DimVar`, `DimExpr`, and `FaceFormula` (added in
|
||
`Interval.lean` / `Face.lean`).
|
||
|
||
Used by `CubicalTransport.Question` for syntactic-classifier
|
||
decidability (`IsFullFace`, `IsEmptyFace`, `IsIntervalLine`,
|
||
`IsUnivLine`, `IsTransport`, `IsPathLine`, …). Cells-spec /
|
||
paideia downstream consumers also benefit (they want to compare
|
||
AST nodes when normalising / dispatching).
|
||
-/
|
||
|
||
import CubicalTransport.Syntax
|
||
|
||
namespace CubicalTransport.DecEq
|
||
|
||
-- ── Mutual decEq block ──────────────────────────────────────────────────────
|
||
-- Every Decidable (a = b) on the 5 AST types and their list/pair
|
||
-- helpers lives here. The block is structurally recursive on the AST
|
||
-- subterms and uses Lean's automatic recognition of OR-patterns to
|
||
-- collapse cross-constructor mismatches into a single `isFalse` arm.
|
||
|
||
mutual
|
||
|
||
def CType.decEq : (a b : CType) → Decidable (a = b)
|
||
| .univ, .univ => isTrue rfl
|
||
| .pi A B, .pi A' B' =>
|
||
match CType.decEq A A', CType.decEq B B' with
|
||
| isTrue hA, isTrue hB => isTrue (by rw [hA, hB])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .path A a b, .path A' a' b' =>
|
||
match CType.decEq A A', CTerm.decEq a a', CTerm.decEq b b' with
|
||
| isTrue hA, isTrue ha, isTrue hb => isTrue (by rw [hA, ha, hb])
|
||
| isFalse h, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .sigma A B, .sigma A' B' =>
|
||
match CType.decEq A A', CType.decEq B B' with
|
||
| isTrue hA, isTrue hB => isTrue (by rw [hA, hB])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .glue ψ T f fInv s r c A, .glue ψ' T' f' fInv' s' r' c' A' =>
|
||
if hψ : ψ = ψ' then
|
||
match CType.decEq T T', CTerm.decEq f f', CTerm.decEq fInv fInv',
|
||
CTerm.decEq s s', CTerm.decEq r r', CTerm.decEq c c',
|
||
CType.decEq A A' with
|
||
| isTrue hT, isTrue hf, isTrue hfI, isTrue hs, isTrue hr, isTrue hc, isTrue hA =>
|
||
isTrue (by rw [hψ, hT, hf, hfI, hs, hr, hc, hA])
|
||
| isFalse h, _, _, _, _, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h, _, _, _, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, isFalse h, _, _, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, _, isFalse h, _, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, _, _, isFalse h, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, _, _, _, isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, _, _, _, _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else
|
||
isFalse (fun heq => hψ (by cases heq; rfl))
|
||
| .ind S ps, .ind S' ps' =>
|
||
match CTypeSchema.decEq S S', decEqListCType ps ps' with
|
||
| isTrue hS, isTrue hp => isTrue (by rw [hS, hp])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .interval, .interval => isTrue rfl
|
||
-- Cross-constructor mismatches. Each row enumerates the (a, b)
|
||
-- shapes where the head constructors differ; `cases heq` discharges
|
||
-- because the eliminator treats them as inhabited-but-equal-only-
|
||
-- between-same-constructor.
|
||
| .univ, .pi _ _ | .univ, .path _ _ _ | .univ, .sigma _ _
|
||
| .univ, .glue _ _ _ _ _ _ _ _ | .univ, .ind _ _ | .univ, .interval
|
||
| .pi _ _, .univ | .pi _ _, .path _ _ _ | .pi _ _, .sigma _ _
|
||
| .pi _ _, .glue _ _ _ _ _ _ _ _ | .pi _ _, .ind _ _ | .pi _ _, .interval
|
||
| .path _ _ _, .univ | .path _ _ _, .pi _ _ | .path _ _ _, .sigma _ _
|
||
| .path _ _ _, .glue _ _ _ _ _ _ _ _ | .path _ _ _, .ind _ _ | .path _ _ _, .interval
|
||
| .sigma _ _, .univ | .sigma _ _, .pi _ _ | .sigma _ _, .path _ _ _
|
||
| .sigma _ _, .glue _ _ _ _ _ _ _ _ | .sigma _ _, .ind _ _ | .sigma _ _, .interval
|
||
| .glue _ _ _ _ _ _ _ _, .univ | .glue _ _ _ _ _ _ _ _, .pi _ _
|
||
| .glue _ _ _ _ _ _ _ _, .path _ _ _ | .glue _ _ _ _ _ _ _ _, .sigma _ _
|
||
| .glue _ _ _ _ _ _ _ _, .ind _ _ | .glue _ _ _ _ _ _ _ _, .interval
|
||
| .ind _ _, .univ | .ind _ _, .pi _ _ | .ind _ _, .path _ _ _
|
||
| .ind _ _, .sigma _ _ | .ind _ _, .glue _ _ _ _ _ _ _ _ | .ind _ _, .interval
|
||
| .interval, .univ | .interval, .pi _ _ | .interval, .path _ _ _
|
||
| .interval, .sigma _ _ | .interval, .glue _ _ _ _ _ _ _ _ | .interval, .ind _ _ =>
|
||
isFalse (fun heq => by cases heq)
|
||
|
||
def CTerm.decEq : (a b : CTerm) → Decidable (a = b)
|
||
| .var x, .var y =>
|
||
if h : x = y then isTrue (by rw [h]) else isFalse (fun heq => h (by cases heq; rfl))
|
||
| .lam x t, .lam y u =>
|
||
if hx : x = y then
|
||
match CTerm.decEq t u with
|
||
| isTrue ht => isTrue (by rw [hx, ht])
|
||
| isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else
|
||
isFalse (fun heq => hx (by cases heq; rfl))
|
||
| .app f a, .app f' a' =>
|
||
match CTerm.decEq f f', CTerm.decEq a a' with
|
||
| isTrue hf, isTrue ha => isTrue (by rw [hf, ha])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .plam i t, .plam j u =>
|
||
if hi : i = j then
|
||
match CTerm.decEq t u with
|
||
| isTrue ht => isTrue (by rw [hi, ht])
|
||
| isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else
|
||
isFalse (fun heq => hi (by cases heq; rfl))
|
||
| .papp t r, .papp u s =>
|
||
if hr : r = s then
|
||
match CTerm.decEq t u with
|
||
| isTrue ht => isTrue (by rw [hr, ht])
|
||
| isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else
|
||
isFalse (fun heq => hr (by cases heq; rfl))
|
||
| .transp i A φ t, .transp j B ψ u =>
|
||
if hi : i = j then if hφ : φ = ψ then
|
||
match CType.decEq A B, CTerm.decEq t u with
|
||
| isTrue hA, isTrue ht => isTrue (by rw [hi, hA, hφ, ht])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hφ (by cases heq; rfl))
|
||
else isFalse (fun heq => hi (by cases heq; rfl))
|
||
| .comp i A φ u t, .comp j B ψ u' t' =>
|
||
if hi : i = j then if hφ : φ = ψ then
|
||
match CType.decEq A B, CTerm.decEq u u', CTerm.decEq t t' with
|
||
| isTrue hA, isTrue hu, isTrue ht => isTrue (by rw [hi, hA, hφ, hu, ht])
|
||
| isFalse h, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hφ (by cases heq; rfl))
|
||
else isFalse (fun heq => hi (by cases heq; rfl))
|
||
| .compN i A cs t, .compN j B cs' t' =>
|
||
if hi : i = j then
|
||
match CType.decEq A B, decEqClauses cs cs', CTerm.decEq t t' with
|
||
| isTrue hA, isTrue hc, isTrue ht => isTrue (by rw [hi, hA, hc, ht])
|
||
| isFalse h, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hi (by cases heq; rfl))
|
||
| .glueIn φ t a, .glueIn ψ u b =>
|
||
if hφ : φ = ψ then
|
||
match CTerm.decEq t u, CTerm.decEq a b with
|
||
| isTrue ht, isTrue ha => isTrue (by rw [hφ, ht, ha])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hφ (by cases heq; rfl))
|
||
| .unglue φ f g, .unglue ψ f' g' =>
|
||
if hφ : φ = ψ then
|
||
match CTerm.decEq f f', CTerm.decEq g g' with
|
||
| isTrue hf, isTrue hg => isTrue (by rw [hφ, hf, hg])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hφ (by cases heq; rfl))
|
||
| .pair a b, .pair a' b' =>
|
||
match CTerm.decEq a a', CTerm.decEq b b' with
|
||
| isTrue ha, isTrue hb => isTrue (by rw [ha, hb])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .fst t, .fst u =>
|
||
match CTerm.decEq t u with
|
||
| isTrue ht => isTrue (by rw [ht])
|
||
| isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .snd t, .snd u =>
|
||
match CTerm.decEq t u with
|
||
| isTrue ht => isTrue (by rw [ht])
|
||
| isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .dimExpr r, .dimExpr s =>
|
||
if h : r = s then isTrue (by rw [h]) else isFalse (fun heq => h (by cases heq; rfl))
|
||
| .ctor S c ps as, .ctor S' c' ps' as' =>
|
||
if hc : c = c' then
|
||
match CTypeSchema.decEq S S', decEqListCType ps ps', decEqListCTerm as as' with
|
||
| isTrue hS, isTrue hp, isTrue ha => isTrue (by rw [hS, hc, hp, ha])
|
||
| isFalse h, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hc (by cases heq; rfl))
|
||
| .indElim S ps m bs t, .indElim S' ps' m' bs' t' =>
|
||
match CTypeSchema.decEq S S', decEqListCType ps ps',
|
||
CTerm.decEq m m', decEqBranches bs bs', CTerm.decEq t t' with
|
||
| isTrue hS, isTrue hp, isTrue hm, isTrue hb, isTrue ht =>
|
||
isTrue (by rw [hS, hp, hm, hb, ht])
|
||
| isFalse h, _, _, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h, _, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, isFalse h, _, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, _, isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, _, _, _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
-- Cross-constructor mismatches. Lean discharges via `cases heq`.
|
||
| .var _, .lam _ _ | .var _, .app _ _ | .var _, .plam _ _ | .var _, .papp _ _
|
||
| .var _, .transp _ _ _ _ | .var _, .comp _ _ _ _ _ | .var _, .compN _ _ _ _
|
||
| .var _, .glueIn _ _ _ | .var _, .unglue _ _ _ | .var _, .pair _ _
|
||
| .var _, .fst _ | .var _, .snd _ | .var _, .dimExpr _ | .var _, .ctor _ _ _ _
|
||
| .var _, .indElim _ _ _ _ _
|
||
| .lam _ _, .var _ | .lam _ _, .app _ _ | .lam _ _, .plam _ _ | .lam _ _, .papp _ _
|
||
| .lam _ _, .transp _ _ _ _ | .lam _ _, .comp _ _ _ _ _ | .lam _ _, .compN _ _ _ _
|
||
| .lam _ _, .glueIn _ _ _ | .lam _ _, .unglue _ _ _ | .lam _ _, .pair _ _
|
||
| .lam _ _, .fst _ | .lam _ _, .snd _ | .lam _ _, .dimExpr _ | .lam _ _, .ctor _ _ _ _
|
||
| .lam _ _, .indElim _ _ _ _ _
|
||
| .app _ _, .var _ | .app _ _, .lam _ _ | .app _ _, .plam _ _ | .app _ _, .papp _ _
|
||
| .app _ _, .transp _ _ _ _ | .app _ _, .comp _ _ _ _ _ | .app _ _, .compN _ _ _ _
|
||
| .app _ _, .glueIn _ _ _ | .app _ _, .unglue _ _ _ | .app _ _, .pair _ _
|
||
| .app _ _, .fst _ | .app _ _, .snd _ | .app _ _, .dimExpr _ | .app _ _, .ctor _ _ _ _
|
||
| .app _ _, .indElim _ _ _ _ _
|
||
| .plam _ _, .var _ | .plam _ _, .lam _ _ | .plam _ _, .app _ _ | .plam _ _, .papp _ _
|
||
| .plam _ _, .transp _ _ _ _ | .plam _ _, .comp _ _ _ _ _ | .plam _ _, .compN _ _ _ _
|
||
| .plam _ _, .glueIn _ _ _ | .plam _ _, .unglue _ _ _ | .plam _ _, .pair _ _
|
||
| .plam _ _, .fst _ | .plam _ _, .snd _ | .plam _ _, .dimExpr _ | .plam _ _, .ctor _ _ _ _
|
||
| .plam _ _, .indElim _ _ _ _ _
|
||
| .papp _ _, .var _ | .papp _ _, .lam _ _ | .papp _ _, .app _ _ | .papp _ _, .plam _ _
|
||
| .papp _ _, .transp _ _ _ _ | .papp _ _, .comp _ _ _ _ _ | .papp _ _, .compN _ _ _ _
|
||
| .papp _ _, .glueIn _ _ _ | .papp _ _, .unglue _ _ _ | .papp _ _, .pair _ _
|
||
| .papp _ _, .fst _ | .papp _ _, .snd _ | .papp _ _, .dimExpr _ | .papp _ _, .ctor _ _ _ _
|
||
| .papp _ _, .indElim _ _ _ _ _
|
||
| .transp _ _ _ _, .var _ | .transp _ _ _ _, .lam _ _ | .transp _ _ _ _, .app _ _
|
||
| .transp _ _ _ _, .plam _ _ | .transp _ _ _ _, .papp _ _ | .transp _ _ _ _, .comp _ _ _ _ _
|
||
| .transp _ _ _ _, .compN _ _ _ _ | .transp _ _ _ _, .glueIn _ _ _
|
||
| .transp _ _ _ _, .unglue _ _ _ | .transp _ _ _ _, .pair _ _ | .transp _ _ _ _, .fst _
|
||
| .transp _ _ _ _, .snd _ | .transp _ _ _ _, .dimExpr _ | .transp _ _ _ _, .ctor _ _ _ _
|
||
| .transp _ _ _ _, .indElim _ _ _ _ _
|
||
| .comp _ _ _ _ _, .var _ | .comp _ _ _ _ _, .lam _ _ | .comp _ _ _ _ _, .app _ _
|
||
| .comp _ _ _ _ _, .plam _ _ | .comp _ _ _ _ _, .papp _ _ | .comp _ _ _ _ _, .transp _ _ _ _
|
||
| .comp _ _ _ _ _, .compN _ _ _ _ | .comp _ _ _ _ _, .glueIn _ _ _
|
||
| .comp _ _ _ _ _, .unglue _ _ _ | .comp _ _ _ _ _, .pair _ _
|
||
| .comp _ _ _ _ _, .fst _ | .comp _ _ _ _ _, .snd _ | .comp _ _ _ _ _, .dimExpr _
|
||
| .comp _ _ _ _ _, .ctor _ _ _ _ | .comp _ _ _ _ _, .indElim _ _ _ _ _
|
||
| .compN _ _ _ _, .var _ | .compN _ _ _ _, .lam _ _ | .compN _ _ _ _, .app _ _
|
||
| .compN _ _ _ _, .plam _ _ | .compN _ _ _ _, .papp _ _ | .compN _ _ _ _, .transp _ _ _ _
|
||
| .compN _ _ _ _, .comp _ _ _ _ _ | .compN _ _ _ _, .glueIn _ _ _
|
||
| .compN _ _ _ _, .unglue _ _ _ | .compN _ _ _ _, .pair _ _ | .compN _ _ _ _, .fst _
|
||
| .compN _ _ _ _, .snd _ | .compN _ _ _ _, .dimExpr _ | .compN _ _ _ _, .ctor _ _ _ _
|
||
| .compN _ _ _ _, .indElim _ _ _ _ _
|
||
| .glueIn _ _ _, .var _ | .glueIn _ _ _, .lam _ _ | .glueIn _ _ _, .app _ _
|
||
| .glueIn _ _ _, .plam _ _ | .glueIn _ _ _, .papp _ _ | .glueIn _ _ _, .transp _ _ _ _
|
||
| .glueIn _ _ _, .comp _ _ _ _ _ | .glueIn _ _ _, .compN _ _ _ _
|
||
| .glueIn _ _ _, .unglue _ _ _ | .glueIn _ _ _, .pair _ _ | .glueIn _ _ _, .fst _
|
||
| .glueIn _ _ _, .snd _ | .glueIn _ _ _, .dimExpr _ | .glueIn _ _ _, .ctor _ _ _ _
|
||
| .glueIn _ _ _, .indElim _ _ _ _ _
|
||
| .unglue _ _ _, .var _ | .unglue _ _ _, .lam _ _ | .unglue _ _ _, .app _ _
|
||
| .unglue _ _ _, .plam _ _ | .unglue _ _ _, .papp _ _ | .unglue _ _ _, .transp _ _ _ _
|
||
| .unglue _ _ _, .comp _ _ _ _ _ | .unglue _ _ _, .compN _ _ _ _
|
||
| .unglue _ _ _, .glueIn _ _ _ | .unglue _ _ _, .pair _ _ | .unglue _ _ _, .fst _
|
||
| .unglue _ _ _, .snd _ | .unglue _ _ _, .dimExpr _ | .unglue _ _ _, .ctor _ _ _ _
|
||
| .unglue _ _ _, .indElim _ _ _ _ _
|
||
| .pair _ _, .var _ | .pair _ _, .lam _ _ | .pair _ _, .app _ _ | .pair _ _, .plam _ _
|
||
| .pair _ _, .papp _ _ | .pair _ _, .transp _ _ _ _ | .pair _ _, .comp _ _ _ _ _
|
||
| .pair _ _, .compN _ _ _ _ | .pair _ _, .glueIn _ _ _ | .pair _ _, .unglue _ _ _
|
||
| .pair _ _, .fst _ | .pair _ _, .snd _ | .pair _ _, .dimExpr _ | .pair _ _, .ctor _ _ _ _
|
||
| .pair _ _, .indElim _ _ _ _ _
|
||
| .fst _, .var _ | .fst _, .lam _ _ | .fst _, .app _ _ | .fst _, .plam _ _
|
||
| .fst _, .papp _ _ | .fst _, .transp _ _ _ _ | .fst _, .comp _ _ _ _ _
|
||
| .fst _, .compN _ _ _ _ | .fst _, .glueIn _ _ _ | .fst _, .unglue _ _ _
|
||
| .fst _, .pair _ _ | .fst _, .snd _ | .fst _, .dimExpr _ | .fst _, .ctor _ _ _ _
|
||
| .fst _, .indElim _ _ _ _ _
|
||
| .snd _, .var _ | .snd _, .lam _ _ | .snd _, .app _ _ | .snd _, .plam _ _
|
||
| .snd _, .papp _ _ | .snd _, .transp _ _ _ _ | .snd _, .comp _ _ _ _ _
|
||
| .snd _, .compN _ _ _ _ | .snd _, .glueIn _ _ _ | .snd _, .unglue _ _ _
|
||
| .snd _, .pair _ _ | .snd _, .fst _ | .snd _, .dimExpr _ | .snd _, .ctor _ _ _ _
|
||
| .snd _, .indElim _ _ _ _ _
|
||
| .dimExpr _, .var _ | .dimExpr _, .lam _ _ | .dimExpr _, .app _ _
|
||
| .dimExpr _, .plam _ _ | .dimExpr _, .papp _ _ | .dimExpr _, .transp _ _ _ _
|
||
| .dimExpr _, .comp _ _ _ _ _ | .dimExpr _, .compN _ _ _ _
|
||
| .dimExpr _, .glueIn _ _ _ | .dimExpr _, .unglue _ _ _ | .dimExpr _, .pair _ _
|
||
| .dimExpr _, .fst _ | .dimExpr _, .snd _ | .dimExpr _, .ctor _ _ _ _
|
||
| .dimExpr _, .indElim _ _ _ _ _
|
||
| .ctor _ _ _ _, .var _ | .ctor _ _ _ _, .lam _ _ | .ctor _ _ _ _, .app _ _
|
||
| .ctor _ _ _ _, .plam _ _ | .ctor _ _ _ _, .papp _ _ | .ctor _ _ _ _, .transp _ _ _ _
|
||
| .ctor _ _ _ _, .comp _ _ _ _ _ | .ctor _ _ _ _, .compN _ _ _ _
|
||
| .ctor _ _ _ _, .glueIn _ _ _ | .ctor _ _ _ _, .unglue _ _ _ | .ctor _ _ _ _, .pair _ _
|
||
| .ctor _ _ _ _, .fst _ | .ctor _ _ _ _, .snd _ | .ctor _ _ _ _, .dimExpr _
|
||
| .ctor _ _ _ _, .indElim _ _ _ _ _
|
||
| .indElim _ _ _ _ _, .var _ | .indElim _ _ _ _ _, .lam _ _ | .indElim _ _ _ _ _, .app _ _
|
||
| .indElim _ _ _ _ _, .plam _ _ | .indElim _ _ _ _ _, .papp _ _
|
||
| .indElim _ _ _ _ _, .transp _ _ _ _ | .indElim _ _ _ _ _, .comp _ _ _ _ _
|
||
| .indElim _ _ _ _ _, .compN _ _ _ _ | .indElim _ _ _ _ _, .glueIn _ _ _
|
||
| .indElim _ _ _ _ _, .unglue _ _ _ | .indElim _ _ _ _ _, .pair _ _
|
||
| .indElim _ _ _ _ _, .fst _ | .indElim _ _ _ _ _, .snd _ | .indElim _ _ _ _ _, .dimExpr _
|
||
| .indElim _ _ _ _ _, .ctor _ _ _ _ =>
|
||
isFalse (fun heq => by cases heq)
|
||
|
||
def CTypeArg.decEq : (a b : CTypeArg) → Decidable (a = b)
|
||
| .type A, .type B =>
|
||
match CType.decEq A B with
|
||
| isTrue h => isTrue (by rw [h])
|
||
| isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
| .param i, .param j =>
|
||
if h : i = j then isTrue (by rw [h]) else isFalse (fun heq => h (by cases heq; rfl))
|
||
| .self, .self => isTrue rfl
|
||
| .dim, .dim => isTrue rfl
|
||
| .type _, .param _ | .type _, .self | .type _, .dim
|
||
| .param _, .type _ | .param _, .self | .param _, .dim
|
||
| .self, .type _ | .self, .param _ | .self, .dim
|
||
| .dim, .type _ | .dim, .param _ | .dim, .self =>
|
||
isFalse (fun heq => by cases heq)
|
||
|
||
def CtorSpec.decEq : (a b : CtorSpec) → Decidable (a = b)
|
||
| .mk n as bs, .mk n' as' bs' =>
|
||
if hn : n = n' then
|
||
match decEqListCTypeArg as as', decEqClauses bs bs' with
|
||
| isTrue ha, isTrue hb => isTrue (by rw [hn, ha, hb])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hn (by cases heq; rfl))
|
||
|
||
def CTypeSchema.decEq : (a b : CTypeSchema) → Decidable (a = b)
|
||
| .mk n np cs, .mk n' np' cs' =>
|
||
if hn : n = n' then if hnp : np = np' then
|
||
match decEqListCtorSpec cs cs' with
|
||
| isTrue hc => isTrue (by rw [hn, hnp, hc])
|
||
| isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hnp (by cases heq; rfl))
|
||
else isFalse (fun heq => hn (by cases heq; rfl))
|
||
|
||
-- ── List / clause / branch helpers ──────────────────────────────────────────
|
||
|
||
def decEqListCType : (xs ys : List CType) → Decidable (xs = ys)
|
||
| [], [] => isTrue rfl
|
||
| [], _ :: _ => isFalse (fun heq => by cases heq)
|
||
| _ :: _, [] => isFalse (fun heq => by cases heq)
|
||
| x :: xs, y :: ys =>
|
||
match CType.decEq x y, decEqListCType xs ys with
|
||
| isTrue hx, isTrue hxs => isTrue (by rw [hx, hxs])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
|
||
def decEqListCTerm : (xs ys : List CTerm) → Decidable (xs = ys)
|
||
| [], [] => isTrue rfl
|
||
| [], _ :: _ => isFalse (fun heq => by cases heq)
|
||
| _ :: _, [] => isFalse (fun heq => by cases heq)
|
||
| x :: xs, y :: ys =>
|
||
match CTerm.decEq x y, decEqListCTerm xs ys with
|
||
| isTrue hx, isTrue hxs => isTrue (by rw [hx, hxs])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
|
||
def decEqListCTypeArg : (xs ys : List CTypeArg) → Decidable (xs = ys)
|
||
| [], [] => isTrue rfl
|
||
| [], _ :: _ => isFalse (fun heq => by cases heq)
|
||
| _ :: _, [] => isFalse (fun heq => by cases heq)
|
||
| x :: xs, y :: ys =>
|
||
match CTypeArg.decEq x y, decEqListCTypeArg xs ys with
|
||
| isTrue hx, isTrue hxs => isTrue (by rw [hx, hxs])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
|
||
def decEqListCtorSpec : (xs ys : List CtorSpec) → Decidable (xs = ys)
|
||
| [], [] => isTrue rfl
|
||
| [], _ :: _ => isFalse (fun heq => by cases heq)
|
||
| _ :: _, [] => isFalse (fun heq => by cases heq)
|
||
| x :: xs, y :: ys =>
|
||
match CtorSpec.decEq x y, decEqListCtorSpec xs ys with
|
||
| isTrue hx, isTrue hxs => isTrue (by rw [hx, hxs])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
|
||
def decEqClauses : (xs ys : List (FaceFormula × CTerm)) → Decidable (xs = ys)
|
||
| [], [] => isTrue rfl
|
||
| [], _ :: _ => isFalse (fun heq => by cases heq)
|
||
| _ :: _, [] => isFalse (fun heq => by cases heq)
|
||
| (φ, t) :: xs, (ψ, u) :: ys =>
|
||
if hφ : φ = ψ then
|
||
match CTerm.decEq t u, decEqClauses xs ys with
|
||
| isTrue ht, isTrue hxs => isTrue (by rw [hφ, ht, hxs])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hφ (by cases heq; rfl))
|
||
|
||
def decEqBranches : (xs ys : List (String × CTerm)) → Decidable (xs = ys)
|
||
| [], [] => isTrue rfl
|
||
| [], _ :: _ => isFalse (fun heq => by cases heq)
|
||
| _ :: _, [] => isFalse (fun heq => by cases heq)
|
||
| (n, t) :: xs, (n', u) :: ys =>
|
||
if hn : n = n' then
|
||
match CTerm.decEq t u, decEqBranches xs ys with
|
||
| isTrue ht, isTrue hxs => isTrue (by rw [hn, ht, hxs])
|
||
| isFalse h, _ => isFalse (fun heq => h (by cases heq; rfl))
|
||
| _, isFalse h => isFalse (fun heq => h (by cases heq; rfl))
|
||
else isFalse (fun heq => hn (by cases heq; rfl))
|
||
|
||
end
|
||
|
||
-- ── Instance declarations ───────────────────────────────────────────────────
|
||
|
||
instance : DecidableEq CType := CType.decEq
|
||
instance : DecidableEq CTerm := CTerm.decEq
|
||
instance : DecidableEq CTypeArg := CTypeArg.decEq
|
||
instance : DecidableEq CtorSpec := CtorSpec.decEq
|
||
instance : DecidableEq CTypeSchema := CTypeSchema.decEq
|
||
|
||
end CubicalTransport.DecEq
|