l3lab/ntp-mathlib huggingface dataset:
theorem adjointifyCounit_left_triangle (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) :
    leftZigzagIso η (adjointifyCounit η ε) = λ_ f ≪≫ (ρ_ f).symm := by
  apply Iso.ext
  dsimp [adjointifyCounit, bicategoricalIsoComp]
  calc
    _ = 𝟙 _ ⊗≫ (η.hom ▷ (f ≫ 𝟙 b) ≫ (f ≫ g) ◁ f ◁ ε.inv) ⊗≫
          f ◁ g ◁ η.inv ▷ f ⊗≫ f ◁ ε.hom := by
      simp [bicategoricalComp]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.hom ▷ (f ≫ g) ≫ (f ≫ g) ◁ η.inv) ▷ f ⊗≫ f ◁ ε.hom := by
      rw [← whisker_exchange η.hom (f ◁ ε.inv)]; simp [bicategoricalComp]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.inv ≫ η.hom) ▷ f ⊗≫ f ◁ ε.hom := by
      rw [← whisker_exchange η.hom η.inv]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ (ε.inv ≫ ε.hom) := by
      rw [Iso.inv_hom_id]; 

Proof state:
B : Type u
inst✝ : Bicategory B
a b c : B
f : a ⟶ b
g : b ⟶ a
η✝ : 𝟙 a ≅ f ≫ g
ε✝ : g ≫ f ≅ 𝟙 b
η : 𝟙 a ≅ f ≫ g
ε : g ≫ f ≅ 𝟙 b
⊢ 𝟙 (𝟙 a ≫ f) ⊗≫ f ◁ ε.inv ⊗≫ 𝟙 (f ≫ g) ▷ f ⊗≫ f ◁ ε.hom = 𝟙 (𝟙 a ≫ f) ⊗≫ f ◁ (ε.inv ≫ ε.hom)

Next tactic:
simp [bicategoricalComp]
theorem adjointifyCounit_left_triangle (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) :
    leftZigzagIso η (adjointifyCounit η ε) = λ_ f ≪≫ (ρ_ f).symm := by
  apply Iso.ext
  dsimp [adjointifyCounit, bicategoricalIsoComp]
  calc
    _ = 𝟙 _ ⊗≫ (η.hom ▷ (f ≫ 𝟙 b) ≫ (f ≫ g) ◁ f ◁ ε.inv) ⊗≫
          f ◁ g ◁ η.inv ▷ f ⊗≫ f ◁ ε.hom := by
      simp [bicategoricalComp]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.hom ▷ (f ≫ g) ≫ (f ≫ g) ◁ η.inv) ▷ f ⊗≫ f ◁ ε.hom := by
      rw [← whisker_exchange η.hom (f ◁ ε.inv)]; simp [bicategoricalComp]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.inv ≫ η.hom) ▷ f ⊗≫ f ◁ ε.hom := by
      rw [← whisker_exchange η.hom η.inv]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ (ε.inv ≫ ε.hom) := by
      rw [Iso.inv_hom_id]; simp [bicategoricalComp]
    _ = _ := by
      

Proof state:
B : Type u
inst✝ : Bicategory B
a b c : B
f : a ⟶ b
g : b ⟶ a
η✝ : 𝟙 a ≅ f ≫ g
ε✝ : g ≫ f ≅ 𝟙 b
η : 𝟙 a ≅ f ≫ g
ε : g ≫ f ≅ 𝟙 b
⊢ 𝟙 (𝟙 a ≫ f) ⊗≫ f ◁ (ε.inv ≫ ε.hom) = (λ_ f).hom ≫ (ρ_ f).inv

Next tactic:
rw [Iso.inv_hom_id]
theorem adjointifyCounit_left_triangle (η : 𝟙 a ≅ f ≫ g) (ε : g ≫ f ≅ 𝟙 b) :
    leftZigzagIso η (adjointifyCounit η ε) = λ_ f ≪≫ (ρ_ f).symm := by
  apply Iso.ext
  dsimp [adjointifyCounit, bicategoricalIsoComp]
  calc
    _ = 𝟙 _ ⊗≫ (η.hom ▷ (f ≫ 𝟙 b) ≫ (f ≫ g) ◁ f ◁ ε.inv) ⊗≫
          f ◁ g ◁ η.inv ▷ f ⊗≫ f ◁ ε.hom := by
      simp [bicategoricalComp]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.hom ▷ (f ≫ g) ≫ (f ≫ g) ◁ η.inv) ▷ f ⊗≫ f ◁ ε.hom := by
      rw [← whisker_exchange η.hom (f ◁ ε.inv)]; simp [bicategoricalComp]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ ε.inv ⊗≫ (η.inv ≫ η.hom) ▷ f ⊗≫ f ◁ ε.hom := by
      rw [← whisker_exchange η.hom η.inv]; coherence
    _ = 𝟙 _ ⊗≫ f ◁ (ε.inv ≫ ε.hom) := by
      rw [Iso.inv_hom_id]; simp [bicategoricalComp]
    _ = _ := by
      rw [Iso.inv_hom_id]; 

Proof state:
B : Type u
inst✝ : Bicategory B
a b c : B
f : a ⟶ b
g : b ⟶ a
η✝ : 𝟙 a ≅ f ≫ g
ε✝ : g ≫ f ≅ 𝟙 b
η : 𝟙 a ≅ f ≫ g
ε : g ≫ f ≅ 𝟙 b
⊢ 𝟙 (𝟙 a ≫ f) ⊗≫ f ◁ 𝟙 (𝟙 b) = (λ_ f).hom ≫ (ρ_ f).inv

Next tactic:
simp [bicategoricalComp]
/-- The identity 1-morphism is an equivalence. -/
def id (a : B) : a ≌ a := ⟨_, _, (ρ_ _).symm, ρ_ _, by 

Proof state:
B : Type u
inst✝ : Bicategory B
a✝ b c : B
f : a✝ ⟶ b
g : b ⟶ a✝
η : 𝟙 a✝ ≅ f ≫ g
ε : g ≫ f ≅ 𝟙 b
a : B
⊢ leftZigzagIso (ρ_ (𝟙 a)).symm (ρ_ (𝟙 a)) = λ_ (𝟙 a) ≪≫ (ρ_ (𝟙 a)).symm

Next tactic:
ext
/-- The identity 1-morphism is an equivalence. -/
def id (a : B) : a ≌ a := ⟨_, _, (ρ_ _).symm, ρ_ _, by ext; 

Proof state:
case w
B : Type u
inst✝ : Bicategory B
a✝ b c : B
f : a✝ ⟶ b
g : b ⟶ a✝
η : 𝟙 a✝ ≅ f ≫ g
ε : g ≫ f ≅ 𝟙 b
a : B
⊢ (leftZigzagIso (ρ_ (𝟙 a)).symm (ρ_ (𝟙 a))).hom = (λ_ (𝟙 a) ≪≫ (ρ_ (𝟙 a)).symm).hom

Next tactic:
simp [bicategoricalIsoComp]
@[to_additive]
theorem one_mk_mul_one_mk [Monoid M] [Mul N] (b₁ b₂ : N) :
    ((1 : M), b₁) * (1, b₂) = (1, b₁ * b₂) :=
  by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Monoid M
inst✝ : Mul N
b₁ b₂ : N
⊢ (1, b₁) * (1, b₂) = (1, b₁ * b₂)

Next tactic:
rw [mk_mul_mk, mul_one]
@[to_additive]
theorem mk_one_mul_mk_one [Mul M] [Monoid N] (a₁ a₂ : M) :
    (a₁, (1 : N)) * (a₂, 1) = (a₁ * a₂, 1) :=
  by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Mul M
inst✝ : Monoid N
a₁ a₂ : M
⊢ (a₁, 1) * (a₂, 1) = (a₁ * a₂, 1)

Next tactic:
rw [mk_mul_mk, mul_one]
instance [SemigroupWithZero M] [SemigroupWithZero N] : SemigroupWithZero (M × N) :=
  { zero_mul := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : SemigroupWithZero M
inst✝ : SemigroupWithZero N
⊢ ∀ (a : M × N), 0 * a = 0

Next tactic:
simp
instance [SemigroupWithZero M] [SemigroupWithZero N] : SemigroupWithZero (M × N) :=
  { zero_mul := by simp,
    mul_zero := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : SemigroupWithZero M
inst✝ : SemigroupWithZero N
⊢ ∀ (a : M × N), a * 0 = 0

Next tactic:
simp
@[to_additive]
instance instMonoid [Monoid M] [Monoid N] : Monoid (M × N) :=
  { npow := fun z a => ⟨Monoid.npow z a.1, Monoid.npow z a.2⟩,
    npow_zero := fun z => ext (Monoid.npow_zero _) (Monoid.npow_zero _),
    npow_succ := fun z a => ext (Monoid.npow_succ _ _) (Monoid.npow_succ _ _),
    one_mul := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Monoid M
inst✝ : Monoid N
⊢ ∀ (a : M × N), 1 * a = a

Next tactic:
simp
@[to_additive]
instance instMonoid [Monoid M] [Monoid N] : Monoid (M × N) :=
  { npow := fun z a => ⟨Monoid.npow z a.1, Monoid.npow z a.2⟩,
    npow_zero := fun z => ext (Monoid.npow_zero _) (Monoid.npow_zero _),
    npow_succ := fun z a => ext (Monoid.npow_succ _ _) (Monoid.npow_succ _ _),
    one_mul := by simp,
    mul_one := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Monoid M
inst✝ : Monoid N
⊢ ∀ (a : M × N), a * 1 = a

Next tactic:
simp
@[to_additive]
instance [DivisionMonoid G] [DivisionMonoid H] : DivisionMonoid (G × H) :=
  { mul_inv_rev := fun a b => ext (mul_inv_rev _ _) (mul_inv_rev _ _),
    inv_eq_of_mul := fun a b h =>
      ext (inv_eq_of_mul_eq_one_right <| congr_arg fst h)
        (inv_eq_of_mul_eq_one_right <| congr_arg snd h),
    inv_inv := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : DivisionMonoid G
inst✝ : DivisionMonoid H
⊢ ∀ (x : G × H), x⁻¹⁻¹ = x

Next tactic:
simp
@[to_additive SubtractionCommMonoid]
instance [DivisionCommMonoid G] [DivisionCommMonoid H] : DivisionCommMonoid (G × H) :=
  { mul_comm := fun ⟨g₁ , h₁⟩ ⟨_, _⟩ => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : DivisionCommMonoid G
inst✝ : DivisionCommMonoid H
x✝¹ x✝ : G × H
g₁ : G
h₁ : H
fst✝ : G
snd✝ : H
⊢ (g₁, h₁) * (fst✝, snd✝) = (fst✝, snd✝) * (g₁, h₁)

Next tactic:
rw [mk_mul_mk, mul_comm g₁, mul_comm h₁]
@[to_additive SubtractionCommMonoid]
instance [DivisionCommMonoid G] [DivisionCommMonoid H] : DivisionCommMonoid (G × H) :=
  { mul_comm := fun ⟨g₁ , h₁⟩ ⟨_, _⟩ => by rw [mk_mul_mk, mul_comm g₁, mul_comm h₁]; 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : DivisionCommMonoid G
inst✝ : DivisionCommMonoid H
x✝¹ x✝ : G × H
g₁ : G
h₁ : H
fst✝ : G
snd✝ : H
⊢ (fst✝ * g₁, snd✝ * h₁) = (fst✝, snd✝) * (g₁, h₁)

Next tactic:
rfl
@[to_additive]
instance [LeftCancelMonoid M] [LeftCancelMonoid N] : LeftCancelMonoid (M × N) :=
  { mul_one := by simp,
    one_mul := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : LeftCancelMonoid M
inst✝ : LeftCancelMonoid N
⊢ ∀ (a : M × N), 1 * a = a

Next tactic:
simp
@[to_additive]
instance [LeftCancelMonoid M] [LeftCancelMonoid N] : LeftCancelMonoid (M × N) :=
  { mul_one := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : LeftCancelMonoid M
inst✝ : LeftCancelMonoid N
⊢ ∀ (a : M × N), a * 1 = a

Next tactic:
simp
@[to_additive]
instance [RightCancelMonoid M] [RightCancelMonoid N] : RightCancelMonoid (M × N) :=
  { mul_one := by simp,
    one_mul := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : RightCancelMonoid M
inst✝ : RightCancelMonoid N
⊢ ∀ (a : M × N), 1 * a = a

Next tactic:
simp
@[to_additive]
instance [RightCancelMonoid M] [RightCancelMonoid N] : RightCancelMonoid (M × N) :=
  { mul_one := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : RightCancelMonoid M
inst✝ : RightCancelMonoid N
⊢ ∀ (a : M × N), a * 1 = a

Next tactic:
simp
@[to_additive]
instance [CancelMonoid M] [CancelMonoid N] : CancelMonoid (M × N) :=
  { mul_right_cancel := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : CancelMonoid M
inst✝ : CancelMonoid N
⊢ ∀ (a b c : M × N), a * b = c * b → a = c

Next tactic:
simp only [mul_left_inj, imp_self, forall_const]
@[to_additive]
instance instCommMonoid [CommMonoid M] [CommMonoid N] : CommMonoid (M × N) :=
  { mul_comm := fun ⟨m₁, n₁⟩ ⟨_, _⟩ => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
x✝¹ x✝ : M × N
m₁ : M
n₁ : N
fst✝ : M
snd✝ : N
⊢ (m₁, n₁) * (fst✝, snd✝) = (fst✝, snd✝) * (m₁, n₁)

Next tactic:
rw [mk_mul_mk, mk_mul_mk, mul_comm m₁, mul_comm n₁]
@[to_additive]
instance [CancelCommMonoid M] [CancelCommMonoid N] : CancelCommMonoid (M × N) :=
  { mul_comm := fun ⟨m₁, n₁⟩ ⟨_, _⟩ => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : CancelCommMonoid M
inst✝ : CancelCommMonoid N
x✝¹ x✝ : M × N
m₁ : M
n₁ : N
fst✝ : M
snd✝ : N
⊢ (m₁, n₁) * (fst✝, snd✝) = (fst✝, snd✝) * (m₁, n₁)

Next tactic:
rw [mk_mul_mk, mk_mul_mk, mul_comm m₁, mul_comm n₁]
instance [MulZeroOneClass M] [MulZeroOneClass N] : MulZeroOneClass (M × N) :=
  { zero_mul := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : MulZeroOneClass M
inst✝ : MulZeroOneClass N
⊢ ∀ (a : M × N), 0 * a = 0

Next tactic:
simp
instance [MulZeroOneClass M] [MulZeroOneClass N] : MulZeroOneClass (M × N) :=
  { zero_mul := by simp,
    mul_zero := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : MulZeroOneClass M
inst✝ : MulZeroOneClass N
⊢ ∀ (a : M × N), a * 0 = 0

Next tactic:
simp
instance [MonoidWithZero M] [MonoidWithZero N] : MonoidWithZero (M × N) :=
  { zero_mul := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : MonoidWithZero M
inst✝ : MonoidWithZero N
⊢ ∀ (a : M × N), 0 * a = 0

Next tactic:
simp
instance [MonoidWithZero M] [MonoidWithZero N] : MonoidWithZero (M × N) :=
  { zero_mul := by simp,
    mul_zero := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : MonoidWithZero M
inst✝ : MonoidWithZero N
⊢ ∀ (a : M × N), a * 0 = 0

Next tactic:
simp
instance [CommMonoidWithZero M] [CommMonoidWithZero N] : CommMonoidWithZero (M × N) :=
  { zero_mul := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : CommMonoidWithZero M
inst✝ : CommMonoidWithZero N
⊢ ∀ (a : M × N), 0 * a = 0

Next tactic:
simp
instance [CommMonoidWithZero M] [CommMonoidWithZero N] : CommMonoidWithZero (M × N) :=
  { zero_mul := by simp,
    mul_zero := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : CommMonoidWithZero M
inst✝ : CommMonoidWithZero N
⊢ ∀ (a : M × N), a * 0 = 0

Next tactic:
simp
@[to_additive]
instance instCommGroup [CommGroup G] [CommGroup H] : CommGroup (G × H) :=
  { mul_comm := fun ⟨g₁, h₁⟩ ⟨_, _⟩ => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : CommGroup G
inst✝ : CommGroup H
x✝¹ x✝ : G × H
g₁ : G
h₁ : H
fst✝ : G
snd✝ : H
⊢ (g₁, h₁) * (fst✝, snd✝) = (fst✝, snd✝) * (g₁, h₁)

Next tactic:
rw [mk_mul_mk, mk_mul_mk, mul_comm g₁, mul_comm h₁]
@[to_additive (attr := simp) prod_unique]
theorem prod_unique (f : M →ₙ* N × P) : ((fst N P).comp f).prod ((snd N P).comp f) = f :=
  ext fun x => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝² : Mul M
inst✝¹ : Mul N
inst✝ : Mul P
f : M →ₙ* N × P
x : M
⊢ (MulHom.prod (comp (fst N P) f) (comp (snd N P) f)) x = f x

Next tactic:
simp only [prod_apply, coe_fst, coe_snd, comp_apply]
@[to_additive]
theorem comp_coprod {Q : Type*} [CommSemigroup Q] (h : P →ₙ* Q) (f : M →ₙ* P) (g : N →ₙ* P) :
    h.comp (f.coprod g) = (h.comp f).coprod (h.comp g) :=
  ext fun x => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝³ : Mul M
inst✝² : Mul N
inst✝¹ : CommSemigroup P
f✝ : M →ₙ* P
g✝ : N →ₙ* P
Q : Type u_8
inst✝ : CommSemigroup Q
h : P →ₙ* Q
f : M →ₙ* P
g : N →ₙ* P
x : M × N
⊢ (comp h (coprod f g)) x = (coprod (comp h f) (comp h g)) x

Next tactic:
simp
@[to_additive (attr := simp) prod_unique]
theorem prod_unique (f : M →* N × P) : ((fst N P).comp f).prod ((snd N P).comp f) = f :=
  ext fun x => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : MulOneClass P
f : M →* N × P
x : M
⊢ (MonoidHom.prod (comp (fst N P) f) (comp (snd N P) f)) x = f x

Next tactic:
simp only [prod_apply, coe_fst, coe_snd, comp_apply]
@[to_additive (attr := simp)]
theorem coprod_comp_inl : (f.coprod g).comp (inl M N) = f :=
  ext fun x => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : CommMonoid P
f : M →* P
g : N →* P
x : M
⊢ (comp (coprod f g) (inl M N)) x = f x

Next tactic:
simp [coprod_apply]
@[to_additive (attr := simp)]
theorem coprod_comp_inr : (f.coprod g).comp (inr M N) = g :=
  ext fun x => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : CommMonoid P
f : M →* P
g : N →* P
x : N
⊢ (comp (coprod f g) (inr M N)) x = g x

Next tactic:
simp [coprod_apply]
@[to_additive (attr := simp)]
theorem coprod_unique (f : M × N →* P) : (f.comp (inl M N)).coprod (f.comp (inr M N)) = f :=
  ext fun x => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : CommMonoid P
f✝ : M →* P
g : N →* P
f : M × N →* P
x : M × N
⊢ (coprod (comp f (inl M N)) (comp f (inr M N))) x = f x

Next tactic:
simp [coprod_apply, inl_apply, inr_apply, ← map_mul]
@[to_additive]
theorem comp_coprod {Q : Type*} [CommMonoid Q] (h : P →* Q) (f : M →* P) (g : N →* P) :
    h.comp (f.coprod g) = (h.comp f).coprod (h.comp g) :=
  ext fun x => by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : CommMonoid P
f✝ : M →* P
g✝ : N →* P
Q : Type u_8
inst✝ : CommMonoid Q
h : P →* Q
f : M →* P
g : N →* P
x : M × N
⊢ (comp h (coprod f g)) x = (coprod (comp h f) (comp h g)) x

Next tactic:
simp
/-- The monoid equivalence between units of a product of two monoids, and the product of the
    units of each monoid. -/
@[to_additive prodAddUnits
      "The additive monoid equivalence between additive units of a product
      of two additive monoids, and the product of the additive units of each additive monoid."]
def prodUnits : (M × N)ˣ ≃* Mˣ × Nˣ where
  toFun := (Units.map (MonoidHom.fst M N)).prod (Units.map (MonoidHom.snd M N))
  invFun u := ⟨(u.1, u.2), (↑u.1⁻¹, ↑u.2⁻¹), by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Monoid M
inst✝ : Monoid N
u : Mˣ × Nˣ
⊢ (↑u.1, ↑u.2) * (↑u.1⁻¹, ↑u.2⁻¹) = 1

Next tactic:
simp
/-- The monoid equivalence between units of a product of two monoids, and the product of the
    units of each monoid. -/
@[to_additive prodAddUnits
      "The additive monoid equivalence between additive units of a product
      of two additive monoids, and the product of the additive units of each additive monoid."]
def prodUnits : (M × N)ˣ ≃* Mˣ × Nˣ where
  toFun := (Units.map (MonoidHom.fst M N)).prod (Units.map (MonoidHom.snd M N))
  invFun u := ⟨(u.1, u.2), (↑u.1⁻¹, ↑u.2⁻¹), by simp, by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Monoid M
inst✝ : Monoid N
u : Mˣ × Nˣ
⊢ (↑u.1⁻¹, ↑u.2⁻¹) * (↑u.1, ↑u.2) = 1

Next tactic:
simp
/-- The monoid equivalence between units of a product of two monoids, and the product of the
    units of each monoid. -/
@[to_additive prodAddUnits
      "The additive monoid equivalence between additive units of a product
      of two additive monoids, and the product of the additive units of each additive monoid."]
def prodUnits : (M × N)ˣ ≃* Mˣ × Nˣ where
  toFun := (Units.map (MonoidHom.fst M N)).prod (Units.map (MonoidHom.snd M N))
  invFun u := ⟨(u.1, u.2), (↑u.1⁻¹, ↑u.2⁻¹), by simp, by simp⟩
  left_inv u := by
    

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Monoid M
inst✝ : Monoid N
u : (M × N)ˣ
⊢ (fun u =>
        { val := (↑u.1, ↑u.2), inv := (↑u.1⁻¹, ↑u.2⁻¹), val_inv := (_ : (↑u.1 * ↑u.1⁻¹, ↑u.2 * ↑u.2⁻¹) = 1),
          inv_val := (_ : (↑u.1⁻¹ * ↑u.1, ↑u.2⁻¹ * ↑u.2) = 1) })
      ((MonoidHom.prod (Units.map (MonoidHom.fst M N)) (Units.map (MonoidHom.snd M N))) u) =
    u

Next tactic:
simp only [MonoidHom.prod_apply, Units.coe_map, MonoidHom.coe_fst, MonoidHom.coe_snd,
      Prod.mk.eta, Units.coe_map_inv, Units.mk_val]
/-- The monoid equivalence between units of a product of two monoids, and the product of the
    units of each monoid. -/
@[to_additive prodAddUnits
      "The additive monoid equivalence between additive units of a product
      of two additive monoids, and the product of the additive units of each additive monoid."]
def prodUnits : (M × N)ˣ ≃* Mˣ × Nˣ where
  toFun := (Units.map (MonoidHom.fst M N)).prod (Units.map (MonoidHom.snd M N))
  invFun u := ⟨(u.1, u.2), (↑u.1⁻¹, ↑u.2⁻¹), by simp, by simp⟩
  left_inv u := by
    simp only [MonoidHom.prod_apply, Units.coe_map, MonoidHom.coe_fst, MonoidHom.coe_snd,
      Prod.mk.eta, Units.coe_map_inv, Units.mk_val]
  right_inv := fun ⟨u₁, u₂⟩ => by
    

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
inst✝¹ : Monoid M
inst✝ : Monoid N
x✝ : Mˣ × Nˣ
u₁ : Mˣ
u₂ : Nˣ
⊢ (MonoidHom.prod (Units.map (MonoidHom.fst M N)) (Units.map (MonoidHom.snd M N)))
      ((fun u =>
          { val := (↑u.1, ↑u.2), inv := (↑u.1⁻¹, ↑u.2⁻¹), val_inv := (_ : (↑u.1 * ↑u.1⁻¹, ↑u.2 * ↑u.2⁻¹) = 1),
            inv_val := (_ : (↑u.1⁻¹ * ↑u.1, ↑u.2⁻¹ * ↑u.2) = 1) })
        (u₁, u₂)) =
    (u₁, u₂)

Next tactic:
simp only [Units.map, MonoidHom.coe_fst, Units.inv_eq_val_inv,
      MonoidHom.coe_snd, MonoidHom.prod_apply, Prod.mk.injEq]
/-- Canonical homomorphism of monoids from `αˣ` into `α × αᵐᵒᵖ`.
Used mainly to define the natural topology of `αˣ`. -/
@[to_additive (attr := simps)
      "Canonical homomorphism of additive monoids from `AddUnits α` into `α × αᵃᵒᵖ`.
      Used mainly to define the natural topology of `AddUnits α`."]
def embedProduct (α : Type*) [Monoid α] : αˣ →* α × αᵐᵒᵖ where
  toFun x := ⟨x, op ↑x⁻¹⟩
  map_one' := by
    

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
α : Type u_8
inst✝ : Monoid α
⊢ (fun x => (↑x, op ↑x⁻¹)) 1 = 1

Next tactic:
simp only [inv_one, eq_self_iff_true, Units.val_one, op_one, Prod.mk_eq_one, and_self_iff]
/-- Canonical homomorphism of monoids from `αˣ` into `α × αᵐᵒᵖ`.
Used mainly to define the natural topology of `αˣ`. -/
@[to_additive (attr := simps)
      "Canonical homomorphism of additive monoids from `AddUnits α` into `α × αᵃᵒᵖ`.
      Used mainly to define the natural topology of `AddUnits α`."]
def embedProduct (α : Type*) [Monoid α] : αˣ →* α × αᵐᵒᵖ where
  toFun x := ⟨x, op ↑x⁻¹⟩
  map_one' := by
    simp only [inv_one, eq_self_iff_true, Units.val_one, op_one, Prod.mk_eq_one, and_self_iff]
  map_mul' x y := by 

Proof state:
A : Type u_1
B : Type u_2
G : Type u_3
H : Type u_4
M : Type u_5
N : Type u_6
P : Type u_7
α : Type u_8
inst✝ : Monoid α
x y : αˣ
⊢ OneHom.toFun { toFun := fun x => (↑x, op ↑x⁻¹), map_one' := (_ : (1, op ↑1⁻¹) = 1) } (x * y) =
    OneHom.toFun { toFun := fun x => (↑x, op ↑x⁻¹), map_one' := (_ : (1, op ↑1⁻¹) = 1) } x *
      OneHom.toFun { toFun := fun x => (↑x, op ↑x⁻¹), map_one' := (_ : (1, op ↑1⁻¹) = 1) } y

Next tactic:
simp only [mul_inv_rev, op_mul, Units.val_mul, Prod.mk_mul_mk]
@[to_additive]
theorem mulIndicator_apply (s : Set α) (f : α → M) (a : α) [Decidable (a ∈ s)] :
    mulIndicator s f a = if a ∈ s then f a else 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
M : Type u_4
N : Type u_5
inst✝² : One M
inst✝¹ : One N
s✝ t : Set α
f✝ g : α → M
a✝ : α
s : Set α
f : α → M
a : α
inst✝ : Decidable (a ∈ s)
⊢ mulIndicator s f a = if a ∈ s then f a else 1

Next tactic:
unfold mulIndicator
@[to_additive]
theorem mulIndicator_apply (s : Set α) (f : α → M) (a : α) [Decidable (a ∈ s)] :
    mulIndicator s f a = if a ∈ s then f a else 1 := by
  unfold mulIndicator
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
M : Type u_4
N : Type u_5
inst✝² : One M
inst✝¹ : One N
s✝ t : Set α
f✝ g : α → M
a✝ : α
s : Set α
f : α → M
a : α
inst✝ : Decidable (a ∈ s)
⊢ (if a ∈ s then f a else 1) = if a ∈ s then f a else 1

Next tactic:
congr
@[to_additive]
theorem mulIndicator_eq_one_or_self (s : Set α) (f : α → M) (a : α) :
    mulIndicator s f a = 1 ∨ mulIndicator s f a = f a := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
M : Type u_4
N : Type u_5
inst✝¹ : One M
inst✝ : One N
s✝ t : Set α
f✝ g : α → M
a✝ : α
s : Set α
f : α → M
a : α
⊢ mulIndicator s f a = 1 ∨ mulIndicator s f a = f a

Next tactic:
by_cases h : a ∈ s
@[to_additive]
theorem mulIndicator_eq_one_or_self (s : Set α) (f : α → M) (a : α) :
    mulIndicator s f a = 1 ∨ mulIndicator s f a = f a := by
  by_cases h : a ∈ s
  · 

Proof state:
case pos
α : Type u_1
β : Type u_2
ι : Type u_3
M : Type u_4
N : Type u_5
inst✝¹ : One M
inst✝ : One N
s✝ t : Set α
f✝ g : α → M
a✝ : α
s : Set α
f : α → M
a : α
h : a ∈ s
⊢ mulIndicator s f a = 1 ∨ mulIndicator s f a = f a

Next tactic:
exact Or.inr (mulIndicator_of_mem h f)
@[to_additive]
theorem mulIndicator_eq_one_or_self (s : Set α) (f : α → M) (a : α) :
    mulIndicator s f a = 1 ∨ mulIndicator s f a = f a := by
  by_cases h : a ∈ s
  · exact Or.inr (mulIndicator_of_mem h f)
  · 

Proof state:
case neg
α : Type u_1
β : Type u_2
ι : Type u_3
M : Type u_4
N : Type u_5
inst✝¹ : One M
inst✝ : One N
s✝ t : Set α
f✝ g : α → M
a✝ : α
s : Set α
f : α → M
a : α
h : a ∉ s
⊢ mulIndicator s f a = 1 ∨ mulIndicator s f a = f a

Next tactic:
exact Or.inl (mulIndicator_of_not_mem h f)
@[to_additive (attr := simp)]
theorem mulIndicator_apply_eq_self : s.mulIndicator f a = f a ↔ a ∉ s → f a = 1 :=
  letI := Classical.dec (a ∈ s)
  ite_eq_left_iff.trans (by 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
M : Type u_4
N : Type u_5
inst✝¹ : One M
inst✝ : One N
s t : Set α
f g : α → M
a : α
this : Decidable (a ∈ s) := Classical.dec (a ∈ s)
⊢ a ∉ s → 1 = f a ↔ a ∉ s → f a = 1

Next tactic:
rw [@eq_comm _ (f a)]
@[to_additive (attr := simp)]
theorem mulIndicator_eq_self : s.mulIndicator f = f ↔ mulSupport f ⊆ s := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
M : Type u_4
N : Type u_5
inst✝¹ : One M
inst✝ : One N
s t : Set α
f g : α → M
a : α
⊢ mulIndicator s f = f ↔ mulSupport f ⊆ s

Next tactic:
simp only [funext_iff, subset_def, mem_mulSupport, mulIndicator_apply_eq_self, not_imp_comm]