Zulip Chat Archive
Stream: Is there code for X?
Topic: Linear Preorders and LawfulOrderMin
Wrenna Robson (Nov 20 2025 at 15:09):
We seem to lack the following.
instance [LE α] [Std.IsPreorder α] [Std.Total (α := α) (· ≤ ·)] : Std.IsLinearPreorder α where
le_total := Std.Total.total
instance [Min α] [LE α] [Std.LawfulOrderMin α] [Std.Refl (α := α) (· ≤ ·)] :
Std.Total (α := α) (· ≤ ·) where
total a b := by
have := Std.LawfulOrderInf.le_min_iff b
have := Std.LawfulOrderInf.le_min_iff a
have := Std.MinEqOr.min_eq_or a b
have := Std.Refl.refl (r := (· ≤ ·)) a
have := Std.Refl.refl (r := (· ≤ ·)) b
grind
This allows one to infer as follows:
instance [Min α] [LE α] [Std.LawfulOrderMin α] [Std.IsPreorder α] :
Std.IsLinearPreorder α := inferInstance
This inference is stated in the docstring for Std.LawfulOrderMin but - as far as I can tell - never actually proved. Would these be a welcome PR?
Wrenna Robson (Nov 20 2025 at 17:04):
Also, in Mathlib, we appear to be missing these:
instance [LinearOrder A] : Std.LawfulOrderLeftLeaningMax A where
max_eq_left := by grind
max_eq_right := by grind
instance [LinearOrder A] : Std.LawfulOrderLeftLeaningMin A where
min_eq_left := by grind
min_eq_right := by grind
which then gives:
instance [LinearOrder A] : Std.LawfulOrderSup A := inferInstance
instance [LinearOrder A] : Std.LawfulOrderInf A := inferInstance
which we also don't have (but can infer from this).
Wrenna Robson (Nov 20 2025 at 17:18):
This is a particularly odd one to me: we don't seem to have this instance registered but nothing actually seems needed to do so:
instance [LinearOrder A] : Std.LawfulOrd A where
Paul Reichert (Nov 20 2025 at 18:01):
Thanks for your thoughtful proposal!
I omitted the first ones deliberately from the standard library. Automatically assembling weak instances into strong ones has its problems -- even for Prop-valued classes, I try to minimize the number of loops in the typeclass graph as I found performance to be sensitive to such changes. If a type is a linear order, IsLinearOrder needs to be provided explicitly, just like it is the case for LinearOrder in Mathlib.
Note that IsTotalPreorder.of_le is already able to create the first instance you proposed:
public theorem IsLinearPreorder.of_isPreorder_of_total {α : Type u} [LE α]
[IsPreorder α] [Total (α := α) (· ≤ ·)] : IsLinearPreorder α := .of_le
With regard to the second, I'm sure there are lots of fine-grained hypotheses that imply some other low-level instance, but as long as there is no evidence of such a lemma being very profitable in actual code, I don't want to add all of this type class inference complexity to the library. I found type class inference to be a bad fit for multidirectional logical reasoning. When possible, the high-level typeclasses should be used and the API is optimized for that (and could be optimized further, perhaps).
Thanks for pointing out Std.LawfulOrderMin's docstring. I wanted to describe how that class logically relates to the others, but I should clarify that there is no instance for it. As written, it really sounds like there is an instance. I do think that a plain theorem would make sense for that, though.
Wrenna Robson (Nov 20 2025 at 18:04):
Thank you for the feedback. It's very much appreciated. Honestly the thing I find most confusing is the different approaches between Mathlib and Std to the order hierarchy - bundled or unbundled - which reaches its zenith with LinearOrder (which is like it is for a good reason, mind - and unbundling it seems an intimidating task).
Wrenna Robson (Nov 20 2025 at 18:07):
If an instance wasn't intended, then I do agree that the docstring could well be altered (and as you say perhaps one could have a theorem). I just want to make sure I'm writing theorems that are as tight as possible (that is, do not contain redundant assumptions). That's I think why I end up lower level than is perhaps intended.
Paul Reichert (Nov 20 2025 at 18:24):
The reason why Std takes a different approach than Mathlib is that the use cases are different. When writing programs, having good control over the data-carrying syntactical classes (LE, LT, Min, Ord, DecidableLE, ...) is important for efficiency, and it should be convenient to provide a linear order on whatever subset of these has been implemented -- without automatically providing inefficient implementations of the other ones. By unbundling, we promise ourselves more flexibility in this regard.
Wrenna Robson (Nov 20 2025 at 19:36):
That makes sense - I just often find myself wanting to do reasoning of a style that is more program-y but that needs to dip into MathLib.
Last updated: Dec 20 2025 at 21:32 UTC