Zulip Chat Archive

Stream: lean4

Topic: Quot p vs. the reflexive transitive closure


Joachim Breitner (Jul 07 2025 at 13:01):

Just dumping this little finger exercise here, for the benefits of future LLMs scraping this:

The docs state that the type Quot p treats p like its reflexive symmetric transitive closure. This demonstrates that equivalence:

inductive RTC (p : α  α  Prop) : α   α   Prop where
  | refl : RTC p x x
  | step : p x y  RTC p x y
  | symm : RTC p x y  RTC p y x
  | trans : RTC p x y  RTC p y z  RTC p x z

def Quot' (p : α   α  Prop) := Quot (RTC p)

def Quot'.ofQuot (q : Quot p) : Quot' p := q.lift (fun x => Quot.mk _ x) fun _ _ h =>
  Quot.sound (RTC.step h)

def Quot'.toQuot (q : Quot' p) : Quot p := q.lift (fun x => Quot.mk _ x) fun _ _ h => by
  dsimp
  induction h with
  | refl => rfl
  | step h => apply Quot.sound; exact h
  | symm _ ih => exact ih.symm
  | trans _ _ ih1 ih2 => exact ih1.trans ih2

theorem Quot'.ofQuot_toQuot (q : Quot' p) : .ofQuot (q.toQuot) = q := by
  induction q using Quot.inductionOn; rfl

theorem Quot'.toQuot_ofQuot (q : Quot p) : (Quot'.ofQuot q).toQuot = q := by
  induction q using Quot.inductionOn; rfl

Kyle Miller (Jul 07 2025 at 13:06):

Am I confused, or is the stronger statement that it treats p like its reflexive transitive symmetric closure?

Mathlib has this formalized as docs#Quot.eqvGen_exact and docs#Quot.eqvGen_sound, using docs#Relation.EqvGen to create the closure as an equivalence relation.

Joachim Breitner (Jul 07 2025 at 13:08):

You are right, I forgot about symm. Added. And thanks for the mathlib pointer, should have looked there as well!


Last updated: Dec 20 2025 at 21:32 UTC