Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
117691e
Adding `Order.Types.Defs` and moving `LinOrd` definition
YanYablonovskiy Jan 16, 2026
e08c49b
Remove `LinOrd` from old location
YanYablonovskiy Jan 16, 2026
6960dd6
Apply suggestions from code review
YanYablonovskiy Jan 16, 2026
c1c3030
Update Mathlib/Order/Types/Defs.lean
YanYablonovskiy Jan 16, 2026
128541e
Review suggestions
YanYablonovskiy Jan 16, 2026
9ee99e6
Run `mk_all`
YanYablonovskiy Jan 16, 2026
ffbea39
Add docs to instance
YanYablonovskiy Jan 16, 2026
36dfe77
Apply review suggestions
YanYablonovskiy Jan 18, 2026
4ef3d57
One more suggestion
YanYablonovskiy Jan 18, 2026
a981b24
Apply suggestions from code review
YanYablonovskiy Jan 18, 2026
9b8172d
Update Defs.lean
YanYablonovskiy Jan 18, 2026
4e287b4
Remove spurious spacing
YanYablonovskiy Jan 18, 2026
f08a940
Apply suggestions from code review
YanYablonovskiy Jan 18, 2026
1f43cc5
Merge branch 'leanprover-community:master' into feat/OrderType_defs
YanYablonovskiy Jan 27, 2026
f18d7ef
Apply suggestions from code review
YanYablonovskiy Jan 27, 2026
e3fdcd3
Remove simp tag
YanYablonovskiy Jan 27, 2026
1f2e93f
Fix over 100 char line
YanYablonovskiy Jan 27, 2026
54b5adc
Add `type_nat_eq` as per suggestion
YanYablonovskiy Jan 28, 2026
f2efcba
Update Mathlib/Order/Types/Defs.lean
YanYablonovskiy Jan 29, 2026
48c0458
Adding `no_expose` to `OrderType.type`
YanYablonovskiy Jan 30, 2026
7e7c6db
Adding `simp` tag to `type_ne_zero`
YanYablonovskiy Jan 30, 2026
d2c7af2
Update Defs.lean
YanYablonovskiy Jan 30, 2026
5cce5a8
Typo
YanYablonovskiy Jan 30, 2026
66c1281
Update Defs.lean
YanYablonovskiy Jan 30, 2026
ab2ce09
Code suggestions
YanYablonovskiy Jan 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Mathlib/Order/Defs/LinearOrder.lean
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,25 @@ instance : Std.LawfulBCmp (compare (α := α)) where

end Ord

/-- The category of linear orders. -/
structure LinOrd where
/-- Construct a bundled `LinOrd` from the underlying type and typeclass. -/
of ::
/-- The underlying linearly ordered type. -/
(carrier : Type*)
[str : LinearOrder carrier]

attribute [instance] LinOrd.str

initialize_simps_projections LinOrd (carrier → coe, -str)

namespace LinOrd

instance : CoeSort LinOrd (Type _) :=
⟨LinOrd.carrier⟩

attribute [coe] LinOrd.carrier

end LinOrd

end LinearOrder
235 changes: 235 additions & 0 deletions Mathlib/Order/Types/Defs.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/-
Copyright (c) 2025 Yan Yablonovskiy. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yan Yablonovskiy
-/
module

public import Mathlib.Order.Hom.Basic

/-!
# Order types

Order types are defined as the quotient of linear orders under order isomorphism. They are endowed
with a preorder, where an OrderType is smaller than another one there is an order embedding
into it.

## Main definitions

* `OrderType`: the type of OrderTypes (in a given universe)
* `OrderType.type α`: given a type `α` with a linear order, this is the corresponding OrderType,

A preorder with a bottom element is registered on order types, where `⊥` is
`0`, the order type corresponding to the empty type.

## Notation

The following are notations in the `OrderType` namespace:

* `ω` is a notation for the order type of `ℕ` with its natural order.

## References

* <https://en.wikipedia.org/wiki/Order_type>
* Dauben, J. W. Georg Cantor: His Mathematics and Philosophy of the Infinite. Princeton,
NJ: Princeton University Press, 1990.
* Enderton, Herbert B. Elements of Set Theory. United Kingdom: Academic Press, 1977.

## Tags

order type, order isomorphism, linear order
-/

@[expose] public noncomputable section

open Function Set Equiv Order

universe u v w w'

variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type w'}

/-- Equivalence relation on linear orders on arbitrary types in universe `u`, given by order
isomorphism. -/
instance OrderType.instSetoid : Setoid LinOrd where
r := fun lin_ord₁ lin_ord₂ ↦ Nonempty (lin_ord₁ ≃o lin_ord₂)
iseqv := ⟨fun _ ↦ ⟨.refl _⟩, fun ⟨e⟩ ↦ ⟨e.symm⟩, fun ⟨e₁⟩ ⟨e₂⟩ ↦ ⟨e₁.trans e₂⟩⟩

/-- `OrderType.{u}` is the type of linear orders in `Type u`, up to order isomorphism. -/
@[pp_with_univ]
def OrderType : Type (u + 1) :=
Quotient OrderType.instSetoid

namespace OrderType

/-- A "canonical" type order-isomorphic to the order type `o`, living in the same universe.
This is defined through the axiom of choice. -/
public def ToType (o : OrderType) : Type u :=
o.out.carrier

instance (o : OrderType) : LinearOrder o.ToType :=
o.out.str

/-! ### Basic properties of the order type -/

/-- The order type of the linear order on `α`. -/
def type (α : Type u) [LinearOrder α] : OrderType :=
⟦⟨α⟩⟧

instance zero : Zero OrderType where
zero := type PEmpty

instance inhabited : Inhabited OrderType :=
⟨0⟩
instance : One OrderType where
one := type PUnit

lemma one_def : (1 : OrderType) = type PUnit := rfl

@[simp]
theorem type_toType (o : OrderType) : type o.ToType = o := surjInv_eq Quot.exists_rep o

theorem type_eq {α β} [LinearOrder α] [LinearOrder β] :
type α = type β ↔ Nonempty (α ≃o β) :=
Quotient.eq'

theorem _root_.RelIso.orderType_eq {α β} [LinearOrder α]
[LinearOrder β] (h : α ≃o β) : type α = type β :=
type_eq.2 ⟨h⟩

@[simp]
theorem type_of_isEmpty [LinearOrder α] [IsEmpty α] : type α = 0 :=
(OrderIso.ofIsEmpty α PEmpty).orderType_eq

@[simp]
theorem type_eq_zero [LinearOrder α] : type α = 0 ↔ IsEmpty α :=
⟨fun h ↦
let ⟨s⟩ := type_eq.1 h
s.toEquiv.isEmpty,
@type_of_isEmpty α _⟩

theorem type_ne_zero_iff [LinearOrder α] : type α ≠ 0 ↔ Nonempty α := by simp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, perhaps this should be type_ne_zero, and below should be type_of_nonempty?

An alternate naming scheme would be to switch the other theorems to e.g. type_eq_zero_iff and type_eq_zero. I think @YaelDillies knows more than me here.

Copy link
Collaborator

@YaelDillies YaelDillies Jan 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is that we don't need the one-way implication because it cannot be used as a rewriting lemma by simp

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonempty α → type α ≠ 0 can most certainly be used by simp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the simp tag to Nonempty α → type α ≠ 0 (which is just one below, type_ne_zero )


theorem type_ne_zero [LinearOrder α] [h : Nonempty α] : type α ≠ 0 :=
type_ne_zero_iff.2 h

@[simp]
theorem type_of_unique [LinearOrder α] [Nonempty α] [Subsingleton α] : type α = 1 := by
cases nonempty_unique α
exact (OrderIso.ofUnique α _).orderType_eq

@[simp]
theorem type_eq_one [LinearOrder α] : type α = 1 ↔ Nonempty (Unique α) :=
⟨fun h ↦ let ⟨s⟩ := type_eq.1 h; ⟨s.toEquiv.unique⟩,
fun ⟨_⟩ ↦ type_of_unique⟩

@[simp]
theorem isEmpty_toType_iff {o : OrderType} : IsEmpty o.ToType ↔ o = 0 := by
rw [← @type_eq_zero o.ToType, type_toType]

instance isEmpty_toType_zero : IsEmpty (ToType 0) :=
isEmpty_toType_iff.2 rfl

@[simp]
theorem nonempty_toType_iff {o : OrderType} : Nonempty o.ToType ↔ o ≠ 0 := by
rw [← @type_ne_zero_iff o.ToType, type_toType]

protected theorem one_ne_zero : (1 : OrderType) ≠ 0 :=
type_ne_zero

instance nontrivial : Nontrivial OrderType.{u} :=
⟨⟨1, 0, OrderType.one_ne_zero⟩⟩

/-- `Quotient.inductionOn` specialized to `OrderType`. -/
@[elab_as_elim]
theorem inductionOn {C : OrderType → Prop} (o : OrderType)
(H : ∀ α [LinearOrder α], C (type α)) : C o :=
Quot.inductionOn o (fun α ↦ H α)

/-- `Quotient.inductionOn₂` specialized to `OrderType`. -/
@[elab_as_elim]
theorem inductionOn₂ {C : OrderType → OrderType → Prop} (o₁ o₂ : OrderType)
(H : ∀ α [LinearOrder α] β [LinearOrder β], C (type α) (type β)) : C o₁ o₂ :=
Quotient.inductionOn₂ o₁ o₂ fun α β ↦ H α β

/-- `Quotient.inductionOn₃` specialized to `OrderType`. -/
@[elab_as_elim]
theorem inductionOn₃ {C : OrderType → OrderType → OrderType → Prop} (o₁ o₂ o₃ : OrderType)
(H : ∀ α [LinearOrder α] β [LinearOrder β] γ [LinearOrder γ],
C (type α) (type β) (type γ)) : C o₁ o₂ o₃ :=
Quotient.inductionOn₃ o₁ o₂ o₃ fun α β γ ↦
H α β γ

/-- To define a function on `OrderType`, it suffices to define it on all linear orders.
-/
def liftOn {δ : Sort v} (o : OrderType) (f : ∀ (α) [LinearOrder α], δ)
(c : ∀ (α) [LinearOrder α] (β) [LinearOrder β],
type α = type β → f α = f β) : δ :=
Quotient.liftOn o (fun w ↦ f w)
fun w₁ w₂ h ↦ c w₁ w₂ (Quotient.sound h)

@[simp]
theorem liftOn_type {δ : Sort v} (f : ∀ (α) [LinearOrder α], δ)
(c : ∀ (α) [LinearOrder α] (β) [LinearOrder β],
type α = type β → f α = f β) {γ} [inst : LinearOrder γ] :
liftOn (type γ) f c = f γ := rfl

/-! ### The order on `OrderType` -/

/--
The order is defined so that `type α ≤ type β` iff there exists an order embedding `α ↪o β`.
-/
instance : Preorder OrderType where
le o₁ o₂ :=
Quotient.liftOn₂ o₁ o₂ (fun r s ↦ Nonempty (r ↪o s))
fun _ _ _ _ ⟨f⟩ ⟨g⟩ ↦ propext
⟨fun ⟨h⟩ ↦ ⟨(f.symm.toOrderEmbedding.trans h).trans g.toOrderEmbedding⟩, fun ⟨h⟩ ↦
⟨(f.toOrderEmbedding.trans h).trans g.symm.toOrderEmbedding⟩⟩
le_refl o := inductionOn o (fun α _ ↦ ⟨(OrderIso.refl _).toOrderEmbedding⟩)
le_trans o₁ o₂ o₃ := inductionOn₃ o₁ o₂ o₃ fun _ _ _ _ _ _ ⟨f⟩ ⟨g⟩ ↦ ⟨f.trans g⟩

instance instNeZeroOne : NeZero (1 : OrderType) :=
⟨OrderType.one_ne_zero⟩

theorem type_le_type_iff {α β} [LinearOrder α]
[LinearOrder β] : type α ≤ type β ↔ Nonempty (α ↪o β) :=
Iff.rfl

theorem type_le_type {α β}
[LinearOrder α] [LinearOrder β] (h : α ↪o β) : type α ≤ type β :=
⟨h⟩

alias _root_.OrderEmbedding.type_le_type := type_le_type
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be?

Suggested change
alias _root_.OrderEmbedding.type_le_type := type_le_type
alias _root_.OrderEmbedding.orderTypeType_le_orderTypeType := type_le_type

I do find this name extremely clunky. Perhaps we can stretch the naming conventions just a bit?

Suggested change
alias _root_.OrderEmbedding.type_le_type := type_le_type
alias _root_.OrderEmbedding.orderType_le_orderType := type_le_type

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current name is okay if we believe that type here unambiguously refers to OrderType.type, which... I could believe?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also Ordinal.type.


@[simp]
protected theorem zero_le (o : OrderType) : 0 ≤ o :=
inductionOn o (fun _ ↦ OrderEmbedding.ofIsEmpty.type_le_type)

instance instOrdBot : OrderBot OrderType where
bot := 0
bot_le := OrderType.zero_le

@[simp]
theorem bot_eq_zero : (⊥ : OrderType) = 0 :=
rfl

@[simp]
protected theorem not_lt_zero (o : OrderType) : ¬o < 0 :=
not_lt_bot

#check lt_of_le_of_lt
#check lt_iff_le_not_ge

@[simp]
theorem pos_iff_ne_zero (o : OrderType) : 0 < o ↔ o ≠ 0 :=
⟨ne_bot_of_gt, fun ho ↦ by simpa [@type_of_isEmpty PEmpty] using
(⟨⟨Function.Embedding.ofIsEmpty, by simp⟩, fun ⟨f⟩ ↦ PEmpty.elim
(f (Classical.choice (OrderType.nonempty_toType_iff.mpr ho)))⟩ : type PEmpty < type o.ToType)⟩

/-- `ω` is the first infinite ordinal, defined as the order type of `ℕ`. -/
public def omega0 : OrderType := type ℕ

@[inherit_doc]
scoped notation "ω" => OrderType.omega0
recommended_spelling "omega0" for "ω" in [omega0, «termω»]

end OrderType
Loading