quotients-and-lifts
Work effectively with Lean 4 quotients in ComputationalPaths (Quot.lift/Quot.ind/Quot.sound), including nested lifts and common proof obligations.
When & Why to Use This Skill
This Claude skill provides a specialized framework for handling Lean 4 quotients and lifts, specifically optimized for the ComputationalPaths codebase. It streamlines the implementation of formal proofs and function definitions involving quotient types like LoopQuot and PiOne. By offering structured patterns for Quot.lift, Quot.ind, and Quot.sound, the skill helps developers navigate the complexities of formal verification, ensuring that functions respect underlying relations and that induction proofs are handled correctly within the Lean 4 ecosystem.
Use Cases
- Defining well-defined functions from quotient types to other domains by providing proofs that the mapping respects the equivalence relation (Quot.lift).
- Simplifying theorem proving for quotient elements by automatically applying quotient induction (Quot.ind) to reduce goals to their representatives.
- Managing complex nested quotient lifts, such as mapping pairs of quotient classes into another quotient, which is common in Higher Inductive Types (HIT) and Seifert-van Kampen (SVK) developments.
- Resolving common Lean 4 proof obligations and debugging 'respects relation' failures by identifying missing symmetry or function extensionality (funext) requirements.
| name | quotients-and-lifts |
|---|---|
| description | Work effectively with Lean 4 quotients in ComputationalPaths (Quot.lift/Quot.ind/Quot.sound), including nested lifts and common proof obligations. |
Quotients & Lifts (Lean 4)
This skill is a practical guide to working with Quot-based quotients in the ComputationalPaths codebase (e.g. LoopQuot, PiOne, group presentations, rewrite quotients).
Core patterns
1) Defining a function out of a quotient: Quot.lift
To define a map Quot r → B, provide:
- a function on representatives
f : A → B - a proof it respects the relation
hf : ∀ a b, r a b → f a = f b
def encode : Quot r → B :=
Quot.lift f (by
intro a b hab
-- show f a = f b
exact hf a b hab)
In this repo, the “respects” proof is often built from an RwEq lemma, e.g. circleEncodePath_rweq in ComputationalPaths/Path/HIT/Circle.lean.
2) Proving something for all quotient elements: Quot.ind
Use quotient induction to reduce to representatives:
theorem myThm (x : Quot r) : P x := by
induction x using Quot.ind with
| _ a =>
-- goal becomes P (Quot.mk _ a) (up to definitional equality)
...
3) Proving equality in a quotient: Quot.sound
When the goal is an equality of quotient terms, typically:
-- goal: Quot.mk r a = Quot.mk r b
exact Quot.sound hab
hab must have the quotient’s underlying relation type (often RwEq in this project). If you have the relation in the “wrong direction”, use symmetry (e.g. rweq_symm).
Nested quotient lifts (Lean 4)
Lean 4 does not provide some Lean 3 conveniences (e.g. patterns like Quot.liftOn2 in older code). Prefer nested Quot.lift:
def f2 : Quot r1 → Quot r2 → C :=
fun x => Quot.lift
(fun a => Quot.lift (fun b => g a b) (by intro b b' hb; exact ...) )
(by intro a a' ha; funext y; -- prove functions are equal
induction y using Quot.ind with
| _ b => ... )
x
This pattern appears in HIT / SVK developments where you map pairs of quotient classes into another quotient.
Practical checklist for “respects relation” proofs
When Quot.lift fails due to the second argument:
- Identify the quotient relation
r(often a rewrite equivalence). - Prove a lemma of the shape
r a b → f a = f b(or→ RwEq (f a) (f b)then turn into equality viaQuot.soundwhere appropriate). - If the lemma naturally produces the reverse direction, wrap with symmetry.
- Use
simplemmas for quotient constructors (e.g.LoopQuot.ofLoop) when applicable.
Common pitfalls (and fixes)
- Wrong obligation shape:
Quot.liftwants equality in the codomain, not a relation proof. If your codomain is itself a quotient, you usually finish withQuot.sound. - Direction mismatch:
Quot.soundexpectsr a b; use symmetry of the relation when you haver b a. - Getting stuck on function equality (nested lifts): use
funext+Quot.indon the remaining quotient argument(s).