@@ -7,7 +7,7 @@ import algebra.group.to_additive
7
7
import tactic.basic
8
8
9
9
/-!
10
- # Typeclasses for (semi)groups and monoid
10
+ # Typeclasses for (semi)groups and monoids
11
11
12
12
In this file we define typeclasses for algebraic structures with one binary operation.
13
13
The classes are named `(add_)?(comm_)?(semigroup|monoid|group)`, where `add_` means that
@@ -62,10 +62,10 @@ def right_mul : G → G → G := λ g : G, λ x : G, x * g
62
62
end has_mul
63
63
64
64
/-- A semigroup is a type with an associative `(*)`. -/
65
- @[protect_proj, ancestor has_mul] class semigroup (G : Type u) extends has_mul G :=
65
+ @[protect_proj, ancestor has_mul, ext ] class semigroup (G : Type u) extends has_mul G :=
66
66
(mul_assoc : ∀ a b c : G, a * b * c = a * (b * c))
67
67
/-- An additive semigroup is a type with an associative `(+)`. -/
68
- @[protect_proj, ancestor has_add] class add_semigroup (G : Type u) extends has_add G :=
68
+ @[protect_proj, ancestor has_add, ext ] class add_semigroup (G : Type u) extends has_add G :=
69
69
(add_assoc : ∀ a b c : G, a + b + c = a + (b + c))
70
70
attribute [to_additive] semigroup
71
71
@@ -85,12 +85,12 @@ instance semigroup.to_is_associative : is_associative G (*) :=
85
85
end semigroup
86
86
87
87
/-- A commutative semigroup is a type with an associative commutative `(*)`. -/
88
- @[protect_proj, ancestor semigroup]
88
+ @[protect_proj, ancestor semigroup, ext ]
89
89
class comm_semigroup (G : Type u) extends semigroup G :=
90
90
(mul_comm : ∀ a b : G, a * b = b * a)
91
91
92
92
/-- A commutative additive semigroup is a type with an associative commutative `(+)`. -/
93
- @[protect_proj, ancestor add_semigroup]
93
+ @[protect_proj, ancestor add_semigroup, ext ]
94
94
class add_comm_semigroup (G : Type u) extends add_semigroup G :=
95
95
(add_comm : ∀ a b : G, a + b = b + a)
96
96
attribute [to_additive] comm_semigroup
@@ -110,12 +110,12 @@ instance comm_semigroup.to_is_commutative : is_commutative G (*) :=
110
110
end comm_semigroup
111
111
112
112
/-- A `left_cancel_semigroup` is a semigroup such that `a * b = a * c` implies `b = c`. -/
113
- @[protect_proj, ancestor semigroup]
113
+ @[protect_proj, ancestor semigroup, ext ]
114
114
class left_cancel_semigroup (G : Type u) extends semigroup G :=
115
115
(mul_left_cancel : ∀ a b c : G, a * b = a * c → b = c)
116
116
/-- An `add_left_cancel_semigroup` is an additive semigroup such that
117
117
`a + b = a + c` implies `b = c`. -/
118
- @[protect_proj, ancestor add_semigroup]
118
+ @[protect_proj, ancestor add_semigroup, ext ]
119
119
class add_left_cancel_semigroup (G : Type u) extends add_semigroup G :=
120
120
(add_left_cancel : ∀ a b c : G, a + b = a + c → b = c)
121
121
attribute [to_additive add_left_cancel_semigroup] left_cancel_semigroup
@@ -146,13 +146,13 @@ theorem mul_ne_mul_right (a : G) {b c : G} : a * b ≠ a * c ↔ b ≠ c :=
146
146
end left_cancel_semigroup
147
147
148
148
/-- A `right_cancel_semigroup` is a semigroup such that `a * b = c * b` implies `a = c`. -/
149
- @[protect_proj, ancestor semigroup]
149
+ @[protect_proj, ancestor semigroup, ext ]
150
150
class right_cancel_semigroup (G : Type u) extends semigroup G :=
151
151
(mul_right_cancel : ∀ a b c : G, a * b = c * b → a = c)
152
152
153
153
/-- An `add_right_cancel_semigroup` is an additive semigroup such that
154
154
`a + b = c + b` implies `a = c`. -/
155
- @[protect_proj, ancestor add_semigroup]
155
+ @[protect_proj, ancestor add_semigroup, ext ]
156
156
class add_right_cancel_semigroup (G : Type u) extends add_semigroup G :=
157
157
(add_right_cancel : ∀ a b c : G, a + b = c + b → a = c)
158
158
attribute [to_additive add_right_cancel_semigroup] right_cancel_semigroup
@@ -198,6 +198,16 @@ class add_zero_class (M : Type u) extends has_zero M, has_add M :=
198
198
199
199
attribute [to_additive] mul_one_class
200
200
201
+ @[ext, to_additive]
202
+ lemma mul_one_class.ext {M : Type u} : ∀ ⦃m₁ m₂ : mul_one_class M⦄, m₁.mul = m₂.mul → m₁ = m₂ :=
203
+ begin
204
+ rintros ⟨one₁, mul₁, one_mul₁, mul_one₁⟩ ⟨one₂, mul₂, one_mul₂, mul_one₂⟩ (rfl : mul₁ = mul₂),
205
+ congr,
206
+ exact (one_mul₂ one₁).symm.trans (mul_one₁ one₂),
207
+ end
208
+
209
+ attribute [ext] add_zero_class.ext
210
+
201
211
section mul_one_class
202
212
variables {M : Type u} [mul_one_class M]
203
213
@@ -352,6 +362,28 @@ class monoid (M : Type u) extends semigroup M, mul_one_class M :=
352
362
353
363
export monoid (npow)
354
364
365
+ @[ext, to_additive]
366
+ lemma monoid.ext {M : Type *} ⦃m₁ m₂ : monoid M⦄ (h_mul : m₁.mul = m₂.mul) : m₁ = m₂ :=
367
+ begin
368
+ unfreezingI {
369
+ cases m₁ with mul₁ _ one₁ one_mul₁ mul_one₁ npow₁ npow_zero₁ npow_succ₁,
370
+ cases m₂ with mul₂ _ one₂ one_mul₂ mul_one₂ npow₂ npow_zero₂ npow_succ₂ },
371
+ change mul₁ = mul₂ at h_mul,
372
+ subst h_mul,
373
+ have h_one : one₁ = one₂,
374
+ { rw ←one_mul₂ one₁,
375
+ exact mul_one₁ one₂ },
376
+ subst h_one,
377
+ have h_npow : npow₁ = npow₂,
378
+ { ext n,
379
+ induction n with d hd,
380
+ { rw [npow_zero₁, npow_zero₂] },
381
+ { rw [npow_succ₁, npow_succ₂, hd] } },
382
+ subst h_npow,
383
+ end
384
+
385
+ attribute [ext] add_monoid.ext
386
+
355
387
section monoid
356
388
variables {M : Type u} [monoid M]
357
389
@@ -388,6 +420,20 @@ class add_comm_monoid (M : Type u) extends add_monoid M, add_comm_semigroup M
388
420
@[protect_proj, ancestor monoid comm_semigroup, to_additive]
389
421
class comm_monoid (M : Type u) extends monoid M, comm_semigroup M
390
422
423
+ @[to_additive]
424
+ lemma comm_monoid.to_monoid_injective {M : Type u} :
425
+ function.injective (@comm_monoid.to_monoid M) :=
426
+ begin
427
+ rintros ⟨⟩ ⟨⟩ h,
428
+ congr'; injection h,
429
+ end
430
+
431
+ @[ext, to_additive]
432
+ lemma comm_monoid.ext {M : Type *} ⦃m₁ m₂ : comm_monoid M⦄ (h_mul : m₁.mul = m₂.mul) : m₁ = m₂ :=
433
+ comm_monoid.to_monoid_injective $ monoid.ext h_mul
434
+
435
+ attribute [ext] add_comm_monoid.ext
436
+
391
437
section left_cancel_monoid
392
438
393
439
/-- An additive monoid in which addition is left-cancellative.
@@ -400,6 +446,21 @@ class add_left_cancel_monoid (M : Type u) extends add_left_cancel_semigroup M, a
400
446
@[protect_proj, ancestor left_cancel_semigroup monoid, to_additive add_left_cancel_monoid]
401
447
class left_cancel_monoid (M : Type u) extends left_cancel_semigroup M, monoid M
402
448
449
+ @[to_additive]
450
+ lemma left_cancel_monoid.to_monoid_injective {M : Type u} :
451
+ function.injective (@left_cancel_monoid.to_monoid M) :=
452
+ begin
453
+ rintros ⟨⟩ ⟨⟩ h,
454
+ congr'; injection h,
455
+ end
456
+
457
+ @[ext, to_additive]
458
+ lemma left_cancel_monoid.ext {M : Type *} ⦃m₁ m₂ : left_cancel_monoid M⦄
459
+ (h_mul : m₁.mul = m₂.mul) : m₁ = m₂ :=
460
+ left_cancel_monoid.to_monoid_injective $ monoid.ext h_mul
461
+
462
+ attribute [ext] add_left_cancel_monoid.ext
463
+
403
464
end left_cancel_monoid
404
465
405
466
section right_cancel_monoid
@@ -414,6 +475,21 @@ class add_right_cancel_monoid (M : Type u) extends add_right_cancel_semigroup M,
414
475
@[protect_proj, ancestor right_cancel_semigroup monoid, to_additive add_right_cancel_monoid]
415
476
class right_cancel_monoid (M : Type u) extends right_cancel_semigroup M, monoid M
416
477
478
+ @[to_additive]
479
+ lemma right_cancel_monoid.to_monoid_injective {M : Type u} :
480
+ function.injective (@right_cancel_monoid.to_monoid M) :=
481
+ begin
482
+ rintros ⟨⟩ ⟨⟩ h,
483
+ congr'; injection h,
484
+ end
485
+
486
+ @[ext, to_additive]
487
+ lemma right_cancel_monoid.ext {M : Type *} ⦃m₁ m₂ : right_cancel_monoid M⦄
488
+ (h_mul : m₁.mul = m₂.mul) : m₁ = m₂ :=
489
+ right_cancel_monoid.to_monoid_injective $ monoid.ext h_mul
490
+
491
+ attribute [ext] add_right_cancel_monoid.ext
492
+
417
493
end right_cancel_monoid
418
494
419
495
section cancel_monoid
@@ -429,6 +505,21 @@ class add_cancel_monoid (M : Type u)
429
505
@[protect_proj, ancestor left_cancel_monoid right_cancel_monoid, to_additive add_cancel_monoid]
430
506
class cancel_monoid (M : Type u) extends left_cancel_monoid M, right_cancel_monoid M
431
507
508
+ @[to_additive]
509
+ lemma cancel_monoid.to_left_cancel_monoid_injective {M : Type u} :
510
+ function.injective (@cancel_monoid.to_left_cancel_monoid M) :=
511
+ begin
512
+ rintros ⟨⟩ ⟨⟩ h,
513
+ congr'; injection h,
514
+ end
515
+
516
+ @[ext, to_additive]
517
+ lemma cancel_monoid.ext {M : Type *} ⦃m₁ m₂ : cancel_monoid M⦄
518
+ (h_mul : m₁.mul = m₂.mul) : m₁ = m₂ :=
519
+ cancel_monoid.to_left_cancel_monoid_injective $ left_cancel_monoid.ext h_mul
520
+
521
+ attribute [ext] add_cancel_monoid.ext
522
+
432
523
/-- Commutative version of add_cancel_monoid. -/
433
524
@[protect_proj, ancestor add_left_cancel_monoid add_comm_monoid]
434
525
class add_cancel_comm_monoid (M : Type u) extends add_left_cancel_monoid M, add_comm_monoid M
@@ -437,6 +528,21 @@ class add_cancel_comm_monoid (M : Type u) extends add_left_cancel_monoid M, add_
437
528
@[protect_proj, ancestor left_cancel_monoid comm_monoid, to_additive add_cancel_comm_monoid]
438
529
class cancel_comm_monoid (M : Type u) extends left_cancel_monoid M, comm_monoid M
439
530
531
+ @[to_additive]
532
+ lemma cancel_comm_monoid.to_comm_monoid_injective {M : Type u} :
533
+ function.injective (@cancel_comm_monoid.to_comm_monoid M) :=
534
+ begin
535
+ rintros ⟨⟩ ⟨⟩ h,
536
+ congr'; injection h,
537
+ end
538
+
539
+ @[ext, to_additive]
540
+ lemma cancel_comm_monoid.ext {M : Type *} ⦃m₁ m₂ : cancel_comm_monoid M⦄
541
+ (h_mul : m₁.mul = m₂.mul) : m₁ = m₂ :=
542
+ cancel_comm_monoid.to_comm_monoid_injective $ comm_monoid.ext h_mul
543
+
544
+ attribute [ext] add_cancel_comm_monoid.ext
545
+
440
546
@[priority 100 , to_additive] -- see Note [lower instance priority]
441
547
instance cancel_comm_monoid.to_cancel_monoid (M : Type u) [cancel_comm_monoid M] :
442
548
cancel_monoid M :=
@@ -485,9 +591,9 @@ class div_inv_monoid (G : Type u) extends monoid G, has_inv G, has_div G :=
485
591
(gpow : ℤ → G → G := gpow_rec)
486
592
(gpow_zero' : ∀ (a : G), gpow 0 a = 1 . try_refl_tac)
487
593
(gpow_succ' :
488
- ∀ (n : ℕ) (a : G), gpow (int.of_nat n.succ) a = a * gpow (int.of_nat n) a . try_refl_tac)
594
+ ∀ (n : ℕ) (a : G), gpow (int.of_nat n.succ) a = a * gpow (int.of_nat n) a . try_refl_tac)
489
595
(gpow_neg' :
490
- ∀ (n : ℕ) (a : G), gpow (-[1 + n]) a = (gpow n.succ a) ⁻¹ . try_refl_tac)
596
+ ∀ (n : ℕ) (a : G), gpow (-[1 + n]) a = (gpow n.succ a)⁻¹ . try_refl_tac)
491
597
492
598
export div_inv_monoid (gpow)
493
599
@@ -515,14 +621,63 @@ class sub_neg_monoid (G : Type u) extends add_monoid G, has_neg G, has_sub G :=
515
621
(gsmul : ℤ → G → G := gsmul_rec)
516
622
(gsmul_zero' : ∀ (a : G), gsmul 0 a = 0 . try_refl_tac)
517
623
(gsmul_succ' :
518
- ∀ (n : ℕ) (a : G), gsmul (int.of_nat n.succ) a = a + gsmul (int.of_nat n) a . try_refl_tac)
624
+ ∀ (n : ℕ) (a : G), gsmul (int.of_nat n.succ) a = a + gsmul (int.of_nat n) a . try_refl_tac)
519
625
(gsmul_neg' :
520
626
∀ (n : ℕ) (a : G), gsmul (-[1 + n]) a = - (gsmul n.succ a) . try_refl_tac)
521
627
522
628
export sub_neg_monoid (gsmul)
523
629
524
630
attribute [to_additive sub_neg_monoid] div_inv_monoid
525
631
632
+ @[ext, to_additive]
633
+ lemma div_inv_monoid.ext {M : Type *} ⦃m₁ m₂ : div_inv_monoid M⦄ (h_mul : m₁.mul = m₂.mul)
634
+ (h_inv : m₁.inv = m₂.inv) : m₁ = m₂ :=
635
+ begin
636
+ let iM : div_inv_monoid M := m₁,
637
+ unfreezingI {
638
+ cases m₁ with mul₁ _ one₁ one_mul₁ mul_one₁ npow₁ npow_zero₁ npow_succ₁ inv₁ div₁
639
+ div_eq_mul_inv₁ gpow₁ gpow_zero'₁ gpow_succ'₁ gpow_neg'₁,
640
+ cases m₂ with mul₂ _ one₂ one_mul₂ mul_one₂ npow₂ npow_zero₂ npow_succ₂ inv₂ div₂
641
+ div_eq_mul_inv₂ gpow₂ gpow_zero'₂ gpow_succ'₂ gpow_neg'₂ },
642
+ change mul₁ = mul₂ at h_mul,
643
+ subst h_mul,
644
+ have h_one : one₁ = one₂,
645
+ { rw ←one_mul₂ one₁,
646
+ exact mul_one₁ one₂ },
647
+ subst h_one,
648
+ have h_npow : npow₁ = npow₂,
649
+ { ext n,
650
+ induction n with d hd,
651
+ { rw [npow_zero₁, npow_zero₂] },
652
+ { rw [npow_succ₁, npow_succ₂, hd] } },
653
+ subst h_npow,
654
+ change inv₁ = inv₂ at h_inv,
655
+ subst h_inv,
656
+ have h_div : div₁ = div₂,
657
+ { ext a b,
658
+ convert (rfl : a * b⁻¹ = a * b⁻¹),
659
+ { exact div_eq_mul_inv₁ a b },
660
+ { exact div_eq_mul_inv₂ a b } },
661
+ subst h_div,
662
+ have h_gpow_aux : ∀ n g, gpow₁ (int.of_nat n) g = gpow₂ (int.of_nat n) g,
663
+ { intros n g,
664
+ induction n with n IH,
665
+ { convert (rfl : (1 : M) = 1 ),
666
+ { exact gpow_zero'₁ g },
667
+ { exact gpow_zero'₂ g } },
668
+ { rw [gpow_succ'₁, gpow_succ'₂, IH] } },
669
+ have h_gpow : gpow₁ = gpow₂,
670
+ { ext z,
671
+ cases z with z z,
672
+ { exact h_gpow_aux z x },
673
+ { rw [gpow_neg'₁, gpow_neg'₂],
674
+ congr',
675
+ exact h_gpow_aux _ _ } },
676
+ subst h_gpow,
677
+ end
678
+
679
+ attribute [ext] sub_neg_monoid.ext
680
+
526
681
@[to_additive]
527
682
lemma div_eq_mul_inv {G : Type u} [div_inv_monoid G] :
528
683
∀ a b : G, a / b = a * b⁻¹ :=
@@ -602,6 +757,45 @@ instance group.to_cancel_monoid : cancel_monoid G :=
602
757
603
758
end group
604
759
760
+ @[to_additive]
761
+ lemma group.to_div_inv_monoid_injective {G : Type *} :
762
+ function.injective (@group.to_div_inv_monoid G) :=
763
+ begin
764
+ rintros ⟨⟩ ⟨⟩ h,
765
+ replace h := div_inv_monoid.mk.inj h,
766
+ dsimp at h,
767
+ rcases h with ⟨rfl, rfl, rfl, rfl, rfl, rfl⟩,
768
+ refl
769
+ end
770
+
771
+ @[ext, to_additive]
772
+ lemma group.ext {G : Type *} ⦃g₁ g₂ : group G⦄ (h_mul : g₁.mul = g₂.mul) : g₁ = g₂ :=
773
+ group.to_div_inv_monoid_injective $ div_inv_monoid.ext h_mul
774
+ begin
775
+ let iG : group G := g₁,
776
+ unfreezingI {
777
+ cases g₁ with mul₁ _ one₁ one_mul₁ mul_one₁ npow₁ npow_zero'₁ npow_succ'₁ inv₁ div₁
778
+ div_eq_mul_inv₁ gpow₁ gpow_zero'₁ gpow_succ'₁ gpow_neg'₁ mul_left_inv₁,
779
+ cases g₂ with mul₂ _ one₂ one_mul₂ mul_one₂ npow₂ npow_zero'₂ npow_succ'₂ inv₂ div₂
780
+ div_eq_mul_inv₂ gpow₂ gpow_zero'₂ gpow_succ'₂ gpow_neg'₂ mul_left_inv₂, },
781
+ change mul₁ = mul₂ at h_mul,
782
+ subst h_mul,
783
+ have h_one : one₁ = one₂,
784
+ { rw ← mul_one₂ one₁,
785
+ exact one_mul₁ one₂ },
786
+ subst h_one,
787
+ have h_inv : inv₁ = inv₂,
788
+ { ext a,
789
+ -- this uses the group.to_cancel_monoid instance, so this lemma can't be moved higher
790
+ rw [← mul_left_inj a],
791
+ convert (rfl : (1 : G) = 1 ),
792
+ { exact mul_left_inv₁ a },
793
+ { exact mul_left_inv₂ a } },
794
+ exact h_inv
795
+ end
796
+
797
+ attribute [ext] add_group.ext
798
+
605
799
/-- A commutative group is a group with commutative `(*)`. -/
606
800
@[protect_proj, ancestor group comm_monoid]
607
801
class comm_group (G : Type u) extends group G, comm_monoid G
@@ -611,6 +805,24 @@ class add_comm_group (G : Type u) extends add_group G, add_comm_monoid G
611
805
attribute [to_additive] comm_group
612
806
attribute [instance, priority 300 ] add_comm_group.to_add_comm_monoid
613
807
808
+ @[to_additive]
809
+ lemma comm_group.to_group_injective {G : Type u} :
810
+ function.injective (@comm_group.to_group G) :=
811
+ begin
812
+ rintros ⟨⟩ ⟨⟩ h,
813
+ replace h := group.mk.inj h,
814
+ dsimp at h,
815
+ rcases h with ⟨rfl, rfl, rfl, rfl, rfl, rfl⟩,
816
+ refl
817
+ end
818
+
819
+ @[ext, to_additive]
820
+ lemma comm_group.ext {G : Type *} ⦃g₁ g₂ : comm_group G⦄
821
+ (h_mul : g₁.mul = g₂.mul) : g₁ = g₂ :=
822
+ comm_group.to_group_injective $ group.ext h_mul
823
+
824
+ attribute [ext] add_comm_group.ext
825
+
614
826
section comm_group
615
827
616
828
variables {G : Type u} [comm_group G]
0 commit comments