Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 48085f1

Browse files
committed
chore(algebra/quaternion): generalize the algebra instance (#18382)
To prevent this generalization forming diamonds, we have to now populate the `nsmul`, `zsmul`, and `qsmul` fields. I use this in another PR to talk about the `R` algebra structure of `quaternion (dual_number R)`. Even without that motivation, this change means that the existing `smul` lemmas now apply to `nsmul`, `zsmul`, and `rat_smul` where previously they did not.
1 parent 34ee86e commit 48085f1

File tree

2 files changed

+74
-31
lines changed

2 files changed

+74
-31
lines changed

src/algebra/quaternion.lean

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def equiv_tuple {R : Type*} (c₁ c₂ : R) : ℍ[R, c₁, c₂] ≃ (fin 4 →
8282
@[simp] lemma mk.eta {R : Type*} {c₁ c₂} : ∀ a : ℍ[R, c₁, c₂], mk a.1 a.2 a.3 a.4 = a
8383
| ⟨a₁, a₂, a₃, a₄⟩ := rfl
8484

85-
variables {R : Type*} [comm_ring R] {c₁ c₂ : R} (r x y z : R) (a b c : ℍ[R, c₁, c₂])
85+
variables {S T R : Type*} [comm_ring R] {c₁ c₂ : R} (r x y z : R) (a b c : ℍ[R, c₁, c₂])
8686

8787
instance : has_coe_t R (ℍ[R, c₁, c₂]) := ⟨λ x, ⟨x, 0, 0, 0⟩⟩
8888

@@ -153,14 +153,46 @@ rfl
153153
a₁ * b₃ + c₁ * a₂ * b₄ + a₃ * b₁ - c₁ * a₄ * b₂,
154154
a₁ * b₄ + a₂ * b₃ - a₃ * b₂ + a₄ * b₁⟩ := rfl
155155

156+
section
157+
variables [has_smul S R] [has_smul T R] (s : S)
158+
159+
/-
160+
The `ring R` argument is not used, but it's also much stronger than the other definitions in this
161+
file need; for instance `quaternion_algebra.has_zero` only really needs `has_zero R`. For
162+
simplicity we just keep things consistent.
163+
-/
164+
@[nolint unused_arguments]
165+
instance : has_smul S ℍ[R, c₁, c₂] :=
166+
{ smul := λ s a, ⟨s • a.1, s • a.2, s • a.3, s • a.4⟩ }
167+
168+
instance [has_smul S T] [is_scalar_tower S T R] : is_scalar_tower S T ℍ[R, c₁, c₂] :=
169+
{ smul_assoc := λ s t x, by ext; exact smul_assoc _ _ _ }
170+
171+
instance [smul_comm_class S T R] : smul_comm_class S T ℍ[R, c₁, c₂] :=
172+
{ smul_comm := λ s t x, by ext; exact smul_comm _ _ _ }
173+
174+
@[simp] lemma smul_re : (s • a).re = s • a.re := rfl
175+
@[simp] lemma smul_im_i : (s • a).im_i = s • a.im_i := rfl
176+
@[simp] lemma smul_im_j : (s • a).im_j = s • a.im_j := rfl
177+
@[simp] lemma smul_im_k : (s • a).im_k = s • a.im_k := rfl
178+
179+
@[simp] lemma smul_mk (re im_i im_j im_k : R) :
180+
s • (⟨re, im_i, im_j, im_k⟩ : ℍ[R, c₁, c₂]) = ⟨s • re, s • im_i, s • im_j, s • im_k⟩ := rfl
181+
182+
end
183+
184+
@[simp, norm_cast] lemma coe_smul [smul_zero_class S R] (s : S) (r : R) :
185+
(↑(s • r) : ℍ[R, c₁, c₂]) = s • ↑r :=
186+
ext _ _ rfl (smul_zero s).symm (smul_zero s).symm (smul_zero s).symm
187+
156188
instance : add_comm_group ℍ[R, c₁, c₂] :=
157189
by refine_struct
158190
{ add := (+),
159191
neg := has_neg.neg,
160192
sub := has_sub.sub,
161193
zero := (0 : ℍ[R, c₁, c₂]),
162-
zsmul := @zsmul_rec _ ⟨(0 : ℍ[R, c₁, c₂])⟩ ⟨(+)⟩ ⟨has_neg.neg⟩,
163-
nsmul := @nsmul_rec _ ⟨(0 : ℍ[R, c₁, c₂])⟩ ⟨(+)⟩ };
194+
nsmul := (•),
195+
zsmul := (•), };
164196
intros; try { refl }; ext; simp; ring_exp
165197

166198
instance : add_group_with_one ℍ[R, c₁, c₂] :=
@@ -196,23 +228,20 @@ by refine_struct
196228
.. quaternion_algebra.add_comm_group };
197229
intros; try { refl }; ext; simp; ring_exp
198230

199-
instance : algebra R ℍ[R, c₁, c₂] :=
200-
{ smul := λ r a, ⟨r * a.1, r * a.2, r * a.3, r * a.4⟩,
201-
to_fun := coe,
202-
map_one' := rfl,
203-
map_zero' := rfl,
204-
map_mul' := λ x y, by ext; simp,
205-
map_add' := λ x y, by ext; simp,
206-
smul_def' := λ r x, by ext; simp,
207-
commutes' := λ r x, by ext; simp [mul_comm] }
208-
209-
@[simp] lemma smul_re : (r • a).re = r • a.re := rfl
210-
@[simp] lemma smul_im_i : (r • a).im_i = r • a.im_i := rfl
211-
@[simp] lemma smul_im_j : (r • a).im_j = r • a.im_j := rfl
212-
@[simp] lemma smul_im_k : (r • a).im_k = r • a.im_k := rfl
231+
@[norm_cast, simp] lemma coe_mul : ((x * y : R) : ℍ[R, c₁, c₂]) = x * y :=
232+
by ext; simp
213233

214-
@[simp] lemma smul_mk (re im_i im_j im_k : R) :
215-
r • (⟨re, im_i, im_j, im_k⟩ : ℍ[R, c₁, c₂]) = ⟨r • re, r • im_i, r • im_j, r • im_k⟩ := rfl
234+
-- TODO: add weaker `mul_action`, `distrib_mul_action`, and `module` instances (and repeat them
235+
-- for `ℍ[R]`)
236+
instance [comm_semiring S] [algebra S R] : algebra S ℍ[R, c₁, c₂] :=
237+
{ smul := (•),
238+
to_fun := λ s, coe (algebra_map S R s),
239+
map_one' := by simpa only [map_one],
240+
map_zero' := by simpa only [map_zero],
241+
map_mul' := λ x y, by rw [map_mul, coe_mul],
242+
map_add' := λ x y, by rw [map_add, coe_add],
243+
smul_def' := λ s x, by ext; simp [algebra.smul_def],
244+
commutes' := λ s x, by ext; simp [algebra.commutes] }
216245

217246
lemma algebra_map_eq (r : R) : algebra_map R ℍ[R,c₁,c₂] r = ⟨r, 0, 0, 0⟩ := rfl
218247

@@ -271,9 +300,6 @@ end
271300
@[norm_cast, simp] lemma coe_sub : ((x - y : R) : ℍ[R, c₁, c₂]) = x - y :=
272301
(algebra_map R ℍ[R, c₁, c₂]).map_sub x y
273302

274-
@[norm_cast, simp] lemma coe_mul : ((x * y : R) : ℍ[R, c₁, c₂]) = x * y :=
275-
(algebra_map R ℍ[R, c₁, c₂]).map_mul x y
276-
277303
@[norm_cast, simp] lemma coe_pow (n : ℕ) : (↑(x ^ n) : ℍ[R, c₁, c₂]) = ↑x ^ n :=
278304
(algebra_map R ℍ[R, c₁, c₂]).map_pow x n
279305

@@ -351,7 +377,9 @@ by rw [←coe_nat_cast, conj_coe]
351377
@[simp, norm_cast] lemma conj_int_cast (z : ℤ) : conj (z : ℍ[R, c₁, c₂]) = z :=
352378
by rw [←coe_int_cast, conj_coe]
353379

354-
lemma conj_smul : conj (r • a) = r • conj a := conj.map_smul r a
380+
@[simp] lemma conj_smul [monoid S] [distrib_mul_action S R] (s : S) (a : ℍ[R, c₁, c₂]) :
381+
conj (s • a) = s • conj a :=
382+
ext _ _ rfl (smul_neg _ _).symm (smul_neg _ _).symm (smul_neg _ _).symm
355383

356384
@[simp] lemma conj_one : conj (1 : ℍ[R, c₁, c₂]) = 1 := conj_coe 1
357385

@@ -426,14 +454,19 @@ quaternion_algebra.equiv_tuple _ _
426454

427455
namespace quaternion
428456

429-
variables {R : Type*} [comm_ring R] (r x y z : R) (a b c : ℍ[R])
457+
variables {S T R : Type*} [comm_ring R] (r x y z : R) (a b c : ℍ[R])
430458

431459
export quaternion_algebra (re im_i im_j im_k)
432460

433461
instance : has_coe_t R ℍ[R] := quaternion_algebra.has_coe_t
434462
instance : ring ℍ[R] := quaternion_algebra.ring
435463
instance : inhabited ℍ[R] := quaternion_algebra.inhabited
436-
instance : algebra R ℍ[R] := quaternion_algebra.algebra
464+
instance [has_smul S R] : has_smul S ℍ[R] := quaternion_algebra.has_smul
465+
instance [has_smul S T] [has_smul S R] [has_smul T R] [is_scalar_tower S T R] :
466+
is_scalar_tower S T ℍ[R] := quaternion_algebra.is_scalar_tower
467+
instance [has_smul S R] [has_smul T R] [smul_comm_class S T R] :
468+
smul_comm_class S T ℍ[R] := quaternion_algebra.smul_comm_class
469+
instance [comm_semiring S] [algebra S R] : algebra S ℍ[R] := quaternion_algebra.algebra
437470
instance : star_ring ℍ[R] := quaternion_algebra.star_ring
438471

439472
@[ext] lemma ext : a.re = b.re → a.im_i = b.im_i → a.im_j = b.im_j → a.im_k = b.im_k → a = b :=
@@ -519,10 +552,14 @@ lemma coe_injective : function.injective (coe : R → ℍ[R]) := quaternion_alge
519552

520553
@[simp] lemma coe_inj {x y : R} : (x : ℍ[R]) = y ↔ x = y := coe_injective.eq_iff
521554

522-
@[simp] lemma smul_re : (r • a).re = r • a.re := rfl
523-
@[simp] lemma smul_im_i : (r • a).im_i = r • a.im_i := rfl
524-
@[simp] lemma smul_im_j : (r • a).im_j = r • a.im_j := rfl
525-
@[simp] lemma smul_im_k : (r • a).im_k = r • a.im_k := rfl
555+
@[simp] lemma smul_re [has_smul S R] (s : S) : (s • a).re = s • a.re := rfl
556+
@[simp] lemma smul_im_i [has_smul S R] (s : S) : (s • a).im_i = s • a.im_i := rfl
557+
@[simp] lemma smul_im_j [has_smul S R] (s : S) : (s • a).im_j = s • a.im_j := rfl
558+
@[simp] lemma smul_im_k [has_smul S R] (s : S) : (s • a).im_k = s • a.im_k := rfl
559+
560+
@[simp, norm_cast] lemma coe_smul [smul_zero_class S R] (s : S) (r : R) :
561+
(↑(s • r) : ℍ[R]) = s • ↑r :=
562+
quaternion_algebra.coe_smul _ _
526563

527564
lemma coe_commutes : ↑r * a = a * r := quaternion_algebra.coe_commutes r a
528565

@@ -589,7 +626,8 @@ quaternion_algebra.conj_nat_cast _
589626
@[simp, norm_cast] lemma conj_int_cast (z : ℤ) : conj (z : ℍ[R]) = z :=
590627
quaternion_algebra.conj_int_cast _
591628

592-
@[simp] lemma conj_smul : conj (r • a) = r • conj a := a.conj_smul r
629+
@[simp] lemma conj_smul [monoid S] [distrib_mul_action S R] (s : S) (a : ℍ[R]) :
630+
conj (s • a) = s • conj a := quaternion_algebra.conj_smul _ _
593631

594632
@[simp] lemma conj_one : conj (1 : ℍ[R]) = 1 := conj_coe 1
595633

@@ -724,6 +762,11 @@ map_zpow₀ (algebra_map R ℍ[R]) x z
724762
instance : division_ring ℍ[R] :=
725763
{ rat_cast := λ q, ↑(q : R),
726764
rat_cast_mk := λ n d hd h, by rw [rat.cast_mk', coe_mul, coe_int_cast, coe_inv, coe_nat_cast],
765+
qsmul := (•),
766+
qsmul_eq_mul' := λ q x, begin
767+
rw coe_mul_eq_smul,
768+
ext; exact division_ring.qsmul_eq_mul' _ _,
769+
end,
727770
.. quaternion.group_with_zero,
728771
.. quaternion.ring }
729772

src/analysis/quaternion.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ noncomputable instance : normed_division_ring ℍ :=
7575

7676
instance : normed_algebra ℝ ℍ :=
7777
{ norm_smul_le := λ a x, (norm_smul a x).le,
78-
to_algebra := quaternion.algebra }
78+
to_algebra := (quaternion.algebra : algebra ℝ ℍ) }
7979

8080
instance : cstar_ring ℍ :=
8181
{ norm_star_mul_self := λ x, (norm_mul _ _).trans $ congr_arg (* ‖x‖) (norm_conj x) }

0 commit comments

Comments
 (0)