Skip to content

Commit cc9b9f3

Browse files
committed
refactor: remove numeric (#177)
This removes the `Numeric` parent for `Semiring` which was used for both coercions and numerals, and replaces it by a low-priority instance for `OfNat` on `Semiring`. The coercion from Nat to R is removed. Numerals are now implemented using `Nat.cast`. As Sebastian has noted, to avoid diamonds for *numerals* it suffices that `Nat.cast n` and `(n : R)` are definitionally equal for every `n : Nat`. It is not necessary that `(Nat.cast ∙)` and `(∙ : R)` are definitionally equal as functions (and after this PR they are not, for most rings). Similarly, `Nat.cast` is carefully defined so that both `0 = 0` and `1 = 1` are true definitionally in any ring. The setup still has a couple of downsides: 1. `OfNat.ofNat` must never be applied to anything except concrete natural numbers (or we get diamonds). 2. `(123456 : R)` is a massive performance issue when executing in the VM. :-/ (Which is not entirely true, in reality it fails quickly due to a stack overflow.) We do not register `Nat.cast` as a coercion because of the performance issues.
1 parent 537323f commit cc9b9f3

File tree

6 files changed

+201
-154
lines changed

6 files changed

+201
-154
lines changed

Mathlib/Algebra/Group/Defs.lean

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,10 @@ end AddMonoid_lemmas
175175
176176
-/
177177

178-
class AddCommMonoid (A : Type u) extends AddMonoid A where
179-
add_comm (a b : A) : a + b = b + a
180-
181-
instance (A : Type u) [AddCommMonoid A] : AddCommSemigroup A where
182-
__ := ‹AddCommMonoid A›
178+
class AddCommMonoid (A : Type u) extends AddMonoid A, AddCommSemigroup A where
179+
-- TODO: doesn't work
180+
zero_add a := (by rw [add_comm, add_zero])
181+
add_zero a := (by rw [add_comm, zero_add])
183182

184183
/-
185184
@@ -199,6 +198,8 @@ class SubNegMonoid (A : Type u) extends AddMonoid A, Neg A, Sub A where
199198
gsmul_succ' (n : ℕ) (a : A) : gsmul (Int.ofNat n.succ) a = a + gsmul (Int.ofNat n) a
200199
gsmul_neg' (n : ℕ) (a : A) : gsmul (Int.negSucc n) a = -(gsmul ↑(n.succ) a)
201200

201+
export SubNegMonoid (sub_eq_add_neg)
202+
202203
/-
203204
204205
### Additive groups
@@ -243,6 +244,9 @@ instance (A : Type u) [AddGroup A] : IsAddLeftCancel A where
243244
add_left_cancel a b c h := by
244245
rw [← neg_add_cancel_left a b, h, neg_add_cancel_left]
245246

247+
lemma eq_of_sub_eq_zero' (h : a - b = 0) : a = b :=
248+
add_right_cancel <| show a + (-b) = b + (-b) by rw [← sub_eq_add_neg, h, add_neg_self]
249+
246250
end AddGroup_lemmas
247251

248252
class AddCommGroup (A : Type u) extends AddGroup A where

Mathlib/Algebra/Ring/Basic.lean

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,45 @@ import Mathlib.Init.Data.Int.Basic
22
import Mathlib.Algebra.GroupWithZero.Defs
33
import Mathlib.Algebra.Group.Basic
44
import Mathlib.Tactic.Spread
5-
/-
6-
7-
# Semirings and rings
5+
import Mathlib.Util.WhatsNew
86

9-
-/
7+
@[reducible, inline]
8+
protected def Nat.cast [Add α] [Zero α] [One α] : Nat → α
9+
| 0 => 0
10+
| 1 => 1
11+
| n + 1 => Nat.cast n + 1
1012

11-
class Numeric (α : Type u) where
12-
ofNat : Nat → α
13+
@[simp] lemma Nat.cast_zero [Add α] [Zero α] [One α] : Nat.cast 0 = (0 : α) := rfl
14+
@[simp] lemma Nat.cast_one [Add α] [Zero α] [One α] : Nat.cast 1 = (1 : α) := rfl
15+
lemma Nat.cast_succ_succ [Add α] [Zero α] [One α] : Nat.cast (n+2) = ((n + 1).cast + 1 : α) := rfl
1316

14-
instance Numeric.OfNat [Numeric α] : OfNat α n := ⟨Numeric.ofNat n⟩
15-
instance [Numeric α] : CoeTail ℕ α := ⟨Numeric.ofNat⟩
17+
@[simp]
18+
lemma Nat.cast_Nat : ∀ {n : Nat}, n.cast = n
19+
| 0 => rfl
20+
| 1 => rfl
21+
| n + 2 => by simp [Nat.cast, cast_Nat]; rfl
1622

17-
theorem ofNat_eq_ofNat (α) (n : ℕ) [Numeric α] : Numeric.ofNat (α := α) n = OfNat.ofNat n := rfl
23+
@[simp]
24+
lemma Nat.cast_Int : ∀ {n : Nat}, n.cast = (n : Int)
25+
| 0 => rfl
26+
| 1 => rfl
27+
| n + 2 => by simp [Nat.cast, cast_Int]; rfl
1828

19-
class Semiring (R : Type u) extends Semigroup R, AddCommSemigroup R, Numeric R where
20-
add_zero (a : R) : a + 0 = a
21-
zero_add (a : R) : 0 + a = a
22-
nsmul : ℕ → R → R := nsmul_rec
23-
nsmul_zero' : ∀ x, nsmul 0 x = 0 -- fill in with tactic once we can do this
24-
nsmul_succ' : ∀ (n : ℕ) x, nsmul n.succ x = x + nsmul n x -- fill in with tactic
29+
class HasNumerals (α : Type u) extends Add α, Zero α, One α
2530

26-
zero_mul (a : R) : 0 * a = 0
27-
mul_zero (a : R) : a * 0 = 0
31+
instance (priority := low) [HasNumerals α] : OfNat α n where
32+
ofNat := n.cast
2833

29-
-- Monoid R
30-
one_mul (a : R) : 1 * a = a
31-
mul_one (a : R) : a * 1 = a
32-
npow : ℕ → R → R := npow_rec
33-
npow_zero' : ∀ x, npow 0 x = 1 -- fill in with tactic once we can do this
34-
npow_succ' : ∀ (n : ℕ) x, npow n.succ x = x * npow n x -- fill in with tactic
34+
/-
35+
# Semirings and rings
36+
-/
3537

38+
class Semiring (R : Type u) extends AddCommMonoid R, MonoidWithZero R, HasNumerals R where
3639
mul_add (a b c : R) : a * (b + c) = a * b + a * c
3740
add_mul (a b c : R) : (a + b) * c = a * c + b * c
38-
ofNat_succ (a : Nat) : ofNat (a + 1) = ofNat a + 1
3941

4042
section Semiring
4143
variable {R} [Semiring R]
42-
open Numeric
4344

4445
instance : MonoidWithZero R where
4546
__ := ‹Semiring R›
@@ -51,31 +52,35 @@ theorem mul_add (a b c : R) : a * (b + c) = a * b + a * c := Semiring.mul_add a
5152

5253
theorem add_mul (a b c : R) : (a + b) * c = a * c + b * c := Semiring.add_mul a b c
5354

54-
@[simp] lemma ofNat_zero : (ofNat 0 : R) = 0 := rfl
55-
@[simp] lemma ofNat_one : (ofNat 1 : R) = 1 := rfl
55+
lemma Nat.cast_succ {R} [Semiring R] {n : ℕ} : Nat.cast (n + 1) = (Nat.cast n + 1 : R) := by
56+
cases n <;> simp [Nat.cast_succ_succ]
5657

57-
@[simp] lemma ofNat_add : ∀ {a b}, (ofNat (a + b) : R) = ofNat a + ofNat b
58-
| a, 0 => (add_zero _).symm
59-
| a, b + 1 => trans (Semiring.ofNat_succ _)
60-
(by simp [Semiring.ofNat_succ, ofNat_add (b := b), add_assoc])
58+
lemma Nat.cast_succ' {R} [Semiring R] {n : ℕ} : Nat.cast n.succ = (Nat.cast n + 1 : R) :=
59+
Nat.cast_succ
6160

62-
@[simp] lemma ofNat_mul : ∀ {a b}, (ofNat (a * b) : R) = ofNat a * ofNat b
63-
| a, 0 => by simp
64-
| a, b + 1 => by simp [Nat.mul_succ, mul_add,
65-
(show ofNat (a * b) = ofNat a * ofNat b from ofNat_mul)]
61+
lemma Nat.cast_add {R} [Semiring R] {m n : ℕ} : (m + n).cast = (m.cast + n.cast : R) := by
62+
induction n generalizing m
63+
case zero => simp
64+
case succ n ih =>
65+
show Nat.cast ((m + n) + 1) = _ + Nat.cast (n + 1)
66+
simp [Nat.cast_succ, ih, add_assoc]
6667

67-
@[simp] theorem ofNat_pow (a n : ℕ) : Numeric.ofNat (a^n) = (Numeric.ofNat a : R)^n := by
68-
induction n with
69-
| zero =>
70-
rw [pow_zero, Nat.pow_zero]
71-
exact rfl
72-
| succ n ih =>
73-
rw [pow_succ, Nat.pow_succ, ofNat_mul, ih]
68+
lemma Nat.cast_mul {R} [Semiring R] {m n : ℕ} : (m * n).cast = (m.cast * n.cast : R) := by
69+
induction n generalizing m <;> simp_all [mul_succ, cast_add, cast_succ', mul_add]
70+
71+
lemma Nat.pow_succ' {m n : Nat} : m ^ n.succ = m * m ^ n := by
72+
rw [Nat.pow_succ, Nat.mul_comm]
73+
74+
lemma Nat.cast_pow {R} [Semiring R] {m n : ℕ} : (m ^ n).cast = (m.cast ^ n : R) := by
75+
induction n generalizing m <;>
76+
simp_all [cast_mul, cast_add, cast_succ', Nat.pow_succ', _root_.pow_succ', pow_zero]
7477

7578
end Semiring
7679

7780
class CommSemiring (R : Type u) extends Semiring R where
7881
mul_comm (a b : R) : a * b = b * a
82+
-- TODO: doesn't work
83+
add_mul a b c := (by rw [mul_comm, mul_add, mul_comm c, mul_comm c])
7984

8085
instance (R : Type u) [CommSemiring R] : CommMonoid R where
8186
__ := ‹CommSemiring R›
@@ -92,6 +97,11 @@ class Ring (R : Type u) extends Semiring R, Neg R, Sub R where
9297

9398
instance {R} [Ring R] : AddCommGroup R := { ‹Ring R› with }
9499

100+
theorem neg_mul_eq_neg_mul {R} [Ring R] (a b : R) : -(a * b) = (-a) * b :=
101+
Eq.symm <| eq_of_sub_eq_zero' <| by
102+
rw [sub_eq_add_neg, neg_neg (a * b) /- TODO: why is arg necessary? -/]
103+
rw [← add_mul, neg_add_self a /- TODO: why is arg necessary? -/, zero_mul]
104+
95105
class CommRing (R : Type u) extends Ring R where
96106
mul_comm (a b : R) : a * b = b * a
97107

@@ -103,15 +113,10 @@ instance (R : Type u) [CommRing R] : CommSemiring R where
103113

104114
namespace Nat
105115

106-
instance : Numeric Nat := ⟨id⟩
107-
108-
@[simp] theorem ofNat_eq_Nat (n : Nat) : Numeric.ofNat n = n := rfl
109-
110116
instance : CommSemiring ℕ where
111117
mul_comm := Nat.mul_comm
112118
mul_add := Nat.left_distrib
113119
add_mul := Nat.right_distrib
114-
ofNat_succ := fun _ => rfl
115120
mul_one := Nat.mul_one
116121
one_mul := Nat.one_mul
117122
npow (n x) := x ^ n
@@ -132,15 +137,12 @@ end Nat
132137

133138
namespace Int
134139

135-
instance : Numeric ℤ := ⟨Int.ofNat⟩
136-
137140
instance : CommRing ℤ where
138141
zero_mul := Int.zero_mul
139142
mul_zero := Int.mul_zero
140143
mul_comm := Int.mul_comm
141144
mul_add := Int.distrib_left
142145
add_mul := Int.distrib_right
143-
ofNat_succ := fun _ => rfl
144146
mul_one := Int.mul_one
145147
one_mul := Int.one_mul
146148
npow (n x) := HPow.hPow x n

0 commit comments

Comments
 (0)