Skip to content

Commit 8a623d7

Browse files
committed
chore: use a type synonym instead of an abbrev for Interval (#37508)
Otherwise, there are conflicting instances between `Interval` and its definition `WithBot ...`, creating diamonds: the multiplication is not defined in the same way (on `WithBot`, we have `0 * bot = 0` while on `Interval` we have `0 * bot = bot`), and the `nsmul` fields are also different. Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr>
1 parent ee31368 commit 8a623d7

File tree

2 files changed

+93
-85
lines changed

2 files changed

+93
-85
lines changed

Mathlib/Algebra/Order/Interval/Basic.lean

Lines changed: 65 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ variable [Preorder α] [One α]
4444
instance : One (NonemptyInterval α) :=
4545
⟨NonemptyInterval.pure 1
4646

47+
@[to_additive]
48+
instance : One (Interval α) :=
49+
⟨(1 : NonemptyInterval α)⟩
50+
4751
namespace NonemptyInterval
4852

4953
@[to_additive (attr := simp) toProd_zero]
@@ -74,9 +78,9 @@ namespace Interval
7478
theorem pure_one : pure (1 : α) = 1 :=
7579
rfl
7680

77-
@[to_additive] lemma one_ne_bot : (1 : Interval α) ≠ ⊥ := pure_ne_bot
81+
@[to_additive (attr := simp)] lemma one_ne_bot : (1 : Interval α) ≠ ⊥ := pure_ne_bot
7882

79-
@[to_additive] lemma bot_ne_one : (⊥ : Interval α) ≠ 1 := bot_ne_pure
83+
@[to_additive (attr := simp)] lemma bot_ne_one : (⊥ : Interval α) ≠ 1 := bot_ne_pure
8084

8185
end Interval
8286

@@ -167,7 +171,7 @@ variable (s t : Interval α)
167171
theorem bot_mul : ⊥ * t = ⊥ :=
168172
WithBot.map₂_bot_left _ _
169173

170-
@[to_additive]
174+
@[to_additive (attr := simp)]
171175
theorem mul_bot : s * ⊥ = ⊥ :=
172176
WithBot.map₂_bot_right _ _
173177

@@ -219,7 +223,7 @@ namespace NonemptyInterval
219223
@[to_additive]
220224
instance commMonoid [CommMonoid α] [Preorder α] [IsOrderedMonoid α] :
221225
CommMonoid (NonemptyInterval α) :=
222-
NonemptyInterval.toProd_injective.commMonoid _ toProd_one toProd_mul toProd_pow
226+
fast_instance% NonemptyInterval.toProd_injective.commMonoid _ toProd_one toProd_mul toProd_pow
223227

224228
end NonemptyInterval
225229

@@ -235,10 +239,9 @@ instance Interval.mulOneClass [CommMonoid α] [Preorder α] [IsOrderedMonoid α]
235239

236240
@[to_additive]
237241
instance Interval.commMonoid [CommMonoid α] [Preorder α] [IsOrderedMonoid α] :
238-
CommMonoid (Interval α) :=
239-
{ Interval.mulOneClass with
240-
mul_comm := fun _ _ => Option.map₂_comm mul_comm
241-
mul_assoc := fun _ _ _ => Option.map₂_assoc mul_assoc }
242+
CommMonoid (Interval α) where
243+
mul_comm := fun _ _ => Option.map₂_comm mul_comm
244+
mul_assoc := fun _ _ _ => Option.map₂_assoc mul_assoc
242245

243246
namespace NonemptyInterval
244247

@@ -294,7 +297,7 @@ namespace NonemptyInterval
294297

295298
instance [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] :
296299
CommSemiring (NonemptyInterval α) :=
297-
NonemptyInterval.toProd_injective.commSemiring _
300+
fast_instance% NonemptyInterval.toProd_injective.commSemiring _
298301
toProd_zero toProd_one toProd_add toProd_mul (swap toProd_nsmul) toProd_pow (fun _ => rfl)
299302

300303
end NonemptyInterval
@@ -482,34 +485,32 @@ protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = pure a ∧ t = pur
482485

483486
instance subtractionCommMonoid {α : Type u}
484487
[AddCommGroup α] [PartialOrder α] [IsOrderedAddMonoid α] :
485-
SubtractionCommMonoid (NonemptyInterval α) :=
486-
{ NonemptyInterval.addCommMonoid with
487-
sub_eq_add_neg := fun s t => by
488-
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
489-
exact sub_eq_add_neg _ _
490-
neg_neg := fun s => by apply NonemptyInterval.ext; exact neg_neg _
491-
neg_add_rev := fun s t => by
492-
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
493-
exact neg_add_rev _ _
494-
neg_eq_of_add := fun s t h => by
495-
obtain ⟨a, b, rfl, rfl, hab⟩ := NonemptyInterval.add_eq_zero_iff.1 h
496-
rw [neg_pure, neg_eq_of_add_eq_zero_right hab]
497-
-- TODO: use a better defeq
498-
zsmul := zsmulRec }
488+
SubtractionCommMonoid (NonemptyInterval α) where
489+
sub_eq_add_neg := fun s t => by
490+
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
491+
exact sub_eq_add_neg _ _
492+
neg_neg := fun s => by apply NonemptyInterval.ext; exact neg_neg _
493+
neg_add_rev := fun s t => by
494+
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
495+
exact neg_add_rev _ _
496+
neg_eq_of_add := fun s t h => by
497+
obtain ⟨a, b, rfl, rfl, hab⟩ := NonemptyInterval.add_eq_zero_iff.1 h
498+
rw [neg_pure, neg_eq_of_add_eq_zero_right hab]
499+
-- TODO: use a better defeq
500+
zsmul := zsmulRec
499501

500502
@[to_additive existing NonemptyInterval.subtractionCommMonoid]
501-
instance divisionCommMonoid : DivisionCommMonoid (NonemptyInterval α) :=
502-
{ NonemptyInterval.commMonoid with
503-
div_eq_mul_inv := fun s t => by
504-
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
505-
exact div_eq_mul_inv _ _
506-
inv_inv := fun s => by apply NonemptyInterval.ext; exact inv_inv _
507-
mul_inv_rev := fun s t => by
508-
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
509-
exact mul_inv_rev _ _
510-
inv_eq_of_mul := fun s t h => by
511-
obtain ⟨a, b, rfl, rfl, hab⟩ := NonemptyInterval.mul_eq_one_iff.1 h
512-
rw [inv_pure, inv_eq_of_mul_eq_one_right hab] }
503+
instance divisionCommMonoid : DivisionCommMonoid (NonemptyInterval α) where
504+
div_eq_mul_inv := fun s t => by
505+
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
506+
exact div_eq_mul_inv _ _
507+
inv_inv := fun s => by apply NonemptyInterval.ext; exact inv_inv _
508+
mul_inv_rev := fun s t => by
509+
refine NonemptyInterval.ext (Prod.ext ?_ ?_) <;>
510+
exact mul_inv_rev _ _
511+
inv_eq_of_mul := fun s t h => by
512+
obtain ⟨a, b, rfl, rfl, hab⟩ := NonemptyInterval.mul_eq_one_iff.1 h
513+
rw [inv_pure, inv_eq_of_mul_eq_one_right hab]
513514

514515
end NonemptyInterval
515516

@@ -524,39 +525,37 @@ protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = pure a ∧ t = pur
524525
cases t
525526
· simp
526527
· simp_rw [← NonemptyInterval.coe_mul_interval, ← NonemptyInterval.coe_one_interval,
527-
WithBot.coe_inj, NonemptyInterval.coe_eq_pure]
528+
Interval.coe_inj, NonemptyInterval.coe_eq_pure]
528529
exact NonemptyInterval.mul_eq_one_iff
529530

530531
instance subtractionCommMonoid {α : Type u}
531532
[AddCommGroup α] [PartialOrder α] [IsOrderedAddMonoid α] :
532-
SubtractionCommMonoid (Interval α) :=
533-
{ Interval.addCommMonoid with
534-
sub_eq_add_neg := by
535-
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (sub_eq_add_neg _ _)
536-
neg_neg := by rintro (_ | s) <;> first | rfl | exact congr_arg WithBot.some (neg_neg _)
537-
neg_add_rev := by
538-
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (neg_add_rev _ _)
539-
neg_eq_of_add := by
540-
rintro (_ | s) (_ | t) h <;>
541-
first
542-
| cases h
543-
| exact congr_arg WithBot.some (neg_eq_of_add_eq_zero_right <| WithBot.coe_injective h)
544-
-- TODO: use a better defeq
545-
zsmul := zsmulRec }
533+
SubtractionCommMonoid (Interval α) where
534+
sub_eq_add_neg := by
535+
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (sub_eq_add_neg _ _)
536+
neg_neg := by rintro (_ | s) <;> first | rfl | exact congr_arg WithBot.some (neg_neg _)
537+
neg_add_rev := by
538+
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (neg_add_rev _ _)
539+
neg_eq_of_add := by
540+
rintro (_ | s) (_ | t) h <;>
541+
first
542+
| cases h
543+
| exact congr_arg WithBot.some (neg_eq_of_add_eq_zero_right <| WithBot.coe_injective h)
544+
-- TODO: use a better defeq
545+
zsmul := zsmulRec
546546

547547
@[to_additive existing Interval.subtractionCommMonoid]
548-
instance divisionCommMonoid : DivisionCommMonoid (Interval α) :=
549-
{ Interval.commMonoid with
550-
div_eq_mul_inv := by
551-
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (div_eq_mul_inv _ _)
552-
inv_inv := by rintro (_ | s) <;> first | rfl | exact congr_arg WithBot.some (inv_inv _)
553-
mul_inv_rev := by
554-
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (mul_inv_rev _ _)
555-
inv_eq_of_mul := by
556-
rintro (_ | s) (_ | t) h <;>
557-
first
558-
| cases h
559-
| exact congr_arg WithBot.some (inv_eq_of_mul_eq_one_right <| WithBot.coe_injective h) }
548+
instance divisionCommMonoid : DivisionCommMonoid (Interval α) where
549+
div_eq_mul_inv := by
550+
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (div_eq_mul_inv _ _)
551+
inv_inv := by rintro (_ | s) <;> first | rfl | exact congr_arg WithBot.some (inv_inv _)
552+
mul_inv_rev := by
553+
rintro (_ | s) (_ | t) <;> first | rfl | exact congr_arg WithBot.some (mul_inv_rev _ _)
554+
inv_eq_of_mul := by
555+
rintro (_ | s) (_ | t) h <;>
556+
first
557+
| cases h
558+
| exact congr_arg WithBot.some (inv_eq_of_mul_eq_one_right <| WithBot.coe_injective h)
560559

561560
end Interval
562561

@@ -635,6 +634,10 @@ theorem length_neg : ∀ s : Interval α, (-s).length = s.length
635634
| ⊥ => rfl
636635
| (s : NonemptyInterval α) => s.length_neg
637636

637+
omit [IsOrderedAddMonoid α] in
638+
@[simp]
639+
theorem length_bot : (⊥ : Interval α).length = 0 := rfl
640+
638641
theorem length_add_le : ∀ s t : Interval α, (s + t).length ≤ s.length + t.length
639642
| ⊥, _ => by simp
640643
| _, ⊥ => by simp

Mathlib/Order/Interval/Basic.lean

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -283,24 +283,21 @@ end NonemptyInterval
283283
We represent intervals either as `⊥` or a nonempty interval given by its endpoints `fst`, `snd`.
284284
To convert intervals to the set of elements between these endpoints, use the coercion
285285
`Interval α → Set α`. -/
286-
abbrev Interval (α : Type*) [LE α] :=
286+
def Interval (α : Type*) [LE α] :=
287287
WithBot (NonemptyInterval α)
288+
deriving Inhabited, LE, OrderBot
288289

289290
namespace Interval
290291

291292
section LE
292293

293294
variable [LE α]
294295

295-
-- The `Inhabited, LE, OrderBot` instances should be constructed by a deriving handler.
296-
-- https://github.com/leanprover-community/mathlib4/issues/380
297-
-- Note(kmill): `Interval` is an `abbrev`, so none of these `instance`s are needed.
298-
instance : Inhabited (Interval α) := WithBot.inhabited
299-
instance : LE (Interval α) := WithBot.instLE
300-
instance : OrderBot (Interval α) := WithBot.instOrderBot
296+
/-- Canonical coercion from nonempty intervals to intervals -/
297+
@[coe] def coe (x : NonemptyInterval α) : Interval α := (x : WithBot _)
301298

302299
instance : Coe (NonemptyInterval α) (Interval α) :=
303-
WithBot.coe
300+
coe
304301

305302
instance canLift : CanLift (Interval α) (NonemptyInterval α) (↑) fun r => r ≠ ⊥ :=
306303
WithBot.canLift
@@ -340,7 +337,7 @@ section Preorder
340337
variable [Preorder α] [Preorder β] [Preorder γ]
341338

342339
instance : Preorder (Interval α) :=
343-
WithBot.instPreorder
340+
inferInstanceAs <| Preorder (WithBot _)
344341

345342
/-- `{a}` as an interval. -/
346343
def pure (a : α) : Interval α :=
@@ -386,10 +383,14 @@ theorem dual_map (f : α →o β) (s : Interval α) : dual (s.map f) = s.dual.ma
386383
· rfl
387384
· exact WithBot.map_comm rfl _
388385

386+
@[simp, norm_cast]
387+
lemma coe_le_coe {s t : NonemptyInterval α} : (s : Interval α) ≤ t ↔ s ≤ t :=
388+
WithBot.coe_le_coe
389+
389390
variable [BoundedOrder α]
390391

391392
instance boundedOrder : BoundedOrder (Interval α) :=
392-
WithBot.instBoundedOrder
393+
inferInstanceAs <| BoundedOrder (WithBot _)
393394

394395
@[simp]
395396
theorem dual_top : dual (⊤ : Interval α) = ⊤ :=
@@ -402,7 +403,7 @@ section PartialOrder
402403
variable [PartialOrder α] [PartialOrder β] {s t : Interval α} {a b : α}
403404

404405
instance partialOrder : PartialOrder (Interval α) :=
405-
WithBot.instPartialOrder
406+
inferInstanceAs <| PartialOrder (WithBot _)
406407

407408
/-- Consider an interval `[a, b]` as the set `[a, b]`. -/
408409
def coeHom : Interval α ↪o Set α :=
@@ -469,7 +470,7 @@ section Lattice
469470
variable [Lattice α]
470471

471472
instance semilatticeSup : SemilatticeSup (Interval α) :=
472-
WithBot.semilatticeSup
473+
inferInstanceAs <| SemilatticeSup (WithBot _)
473474

474475
section Decidable
475476

@@ -483,8 +484,7 @@ instance lattice : Lattice (Interval α) :=
483484
| _, ⊥ => ⊥
484485
| some s, some t =>
485486
if h : s.fst ≤ t.snd ∧ t.fst ≤ s.snd then
486-
WithBot.some
487-
⟨⟨s.fst ⊔ t.fst, s.snd ⊓ t.snd⟩,
487+
coe ⟨⟨s.fst ⊔ t.fst, s.snd ⊓ t.snd⟩,
488488
sup_le (le_inf s.fst_le_snd h.1) <| le_inf h.2 t.fst_le_snd⟩
489489
else
490490
inf_le_left := fun s t =>
@@ -514,8 +514,8 @@ instance lattice : Lattice (Interval α) :=
514514
lift t to NonemptyInterval α using ne_bot_of_le_ne_bot WithBot.coe_ne_bot hb
515515
lift c to NonemptyInterval α using ne_bot_of_le_ne_bot WithBot.coe_ne_bot hc
516516
change _ ≤ dite _ _ _
517-
simp only [WithBot.coe_le_coe] at hb hc ⊢
518-
rw [dif_pos, WithBot.coe_le_coe]
517+
simp only [Interval.coe_le_coe] at hb hc ⊢
518+
rw [dif_pos, Interval.coe_le_coe]
519519
· exact ⟨sup_le hb.1 hc.1, le_inf hb.2 hc.2
520520
-- Porting note: had to add the next 6 lines including the changes because
521521
-- it seems that lean cannot automatically turn `NonemptyInterval.toDualProd s`
@@ -529,6 +529,12 @@ instance lattice : Lattice (Interval α) :=
529529
-- Porting note: originally it just had `hb.1` etc. in this next line
530530
exact ⟨hb₁.trans <| s.fst_le_snd.trans hc₂, hc₁.trans <| s.fst_le_snd.trans hb₂⟩ }
531531

532+
lemma inf_coe (s t : NonemptyInterval α) :
533+
(s : Interval α) ⊓ t = if h : s.fst ≤ t.snd ∧ t.fst ≤ s.snd then
534+
coe ⟨⟨s.fst ⊔ t.fst, s.snd ⊓ t.snd⟩,
535+
sup_le (le_inf s.fst_le_snd h.1) <| le_inf h.2 t.fst_le_snd⟩
536+
else ⊥ := rfl
537+
532538
@[simp, norm_cast]
533539
theorem coe_inf : ∀ s t : Interval α, (↑(s ⊓ t) : Set α) = ↑s ∩ ↑t
534540
| ⊥, _ => by
@@ -538,8 +544,7 @@ theorem coe_inf : ∀ s t : Interval α, (↑(s ⊓ t) : Set α) = ↑s ∩ ↑t
538544
rw [inf_bot_eq]
539545
exact (inter_empty _).symm
540546
| (s : NonemptyInterval α), (t : NonemptyInterval α) => by
541-
simp only [Min.min, coe_coe, NonemptyInterval.coe_def, Icc_inter_Icc,
542-
SemilatticeInf.inf, Lattice.inf]
547+
simp only [coe_coe, NonemptyInterval.coe_def, Icc_inter_Icc, inf_coe]
543548
split_ifs with h
544549
· simp only [coe_coe, NonemptyInterval.coe_def]
545550
· refine (Icc_eq_empty <| mt ?_ h).symm
@@ -562,7 +567,7 @@ namespace NonemptyInterval
562567

563568
section Preorder
564569

565-
variable [Preorder α] {s : NonemptyInterval α} {a : α}
570+
variable [Preorder α] {s t : NonemptyInterval α} {a : α}
566571

567572
@[simp, norm_cast]
568573
theorem coe_pure_interval (a : α) : (pure a : Interval α) = Interval.pure a :=
@@ -601,7 +606,7 @@ noncomputable instance completeLattice [DecidableLE α] : CompleteLattice (Inter
601606
sSup := fun S =>
602607
if h : S ⊆ {⊥} then
603608
else
604-
WithBot.some
609+
coe
605610
⟨⟨⨅ (s : NonemptyInterval α) (_ : ↑s ∈ S), s.fst,
606611
⨆ (s : NonemptyInterval α) (_ : ↑s ∈ S), s.snd⟩, by
607612
obtain ⟨s, hs, ha⟩ := not_subset.1 h
@@ -617,7 +622,7 @@ noncomputable instance completeLattice [DecidableLE α] : CompleteLattice (Inter
617622
· -- Porting note: This case was
618623
-- `exact WithBot.some_le_some.2 ⟨iInf₂_le _ ha, le_iSup₂_of_le _ ha le_rfl⟩`
619624
-- but there seems to be a defEq-problem at `iInf₂_le` that lean cannot resolve yet.
620-
apply WithBot.coe_le_coe.2
625+
apply Interval.coe_le_coe.2
621626
constructor
622627
· apply iInf₂_le
623628
exact ha
@@ -628,15 +633,15 @@ noncomputable instance completeLattice [DecidableLE α] : CompleteLattice (Inter
628633
obtain ⟨b, hs, hb⟩ := not_subset.1 h
629634
lift s to NonemptyInterval α using ne_bot_of_le_ne_bot hb (ha hs)
630635
exact
631-
WithBot.coe_le_coe.2
636+
Interval.coe_le_coe.2
632637
⟨le_iInf₂ fun c hc => (WithBot.coe_le_coe.1 <| ha hc).1,
633638
iSup₂_le fun c hc => (WithBot.coe_le_coe.1 <| ha hc).2
634639
sInf := fun S =>
635640
if h :
636641
⊥ ∉ S ∧
637642
∀ ⦃s : NonemptyInterval α⦄,
638643
↑s ∈ S → ∀ ⦃t : NonemptyInterval α⦄, ↑t ∈ S → s.fst ≤ t.snd then
639-
WithBot.some
644+
coe
640645
⟨⟨⨆ (s : NonemptyInterval α) (_ : ↑s ∈ S), s.fst,
641646
⨅ (s : NonemptyInterval α) (_ : ↑s ∈ S), s.snd⟩,
642647
iSup₂_le fun s hs => le_iInf₂ <| h.2 hs⟩

0 commit comments

Comments
 (0)