l3lab/ntp-mathlib huggingface dataset:
theorem antidiagonal_eq_map_powerset [DecidableEq α] (s : Multiset α) :
    s.antidiagonal = s.powerset.map fun t ↦ (s - t, t) := by
  induction' s using Multiset.induction_on with a s hs
  · simp only [antidiagonal_zero, powerset_zero, zero_tsub, map_singleton]
  · simp_rw [antidiagonal_cons, powerset_cons, map_add, hs, map_map, Function.comp, Prod.map_mk,
      id.def, sub_cons, erase_cons_head]
    

Proof state:
case cons
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
a : α
s : Multiset α
hs : antidiagonal s = map (fun t => (s - t, t)) (powerset s)
⊢ map (fun x => (s - x, a ::ₘ x)) (powerset s) + map (fun x => (a ::ₘ (s - x), x)) (powerset s) =
    map (fun x => (a ::ₘ s - x, x)) (powerset s) + map (fun x => (s - x, a ::ₘ x)) (powerset s)

Next tactic:
rw [add_comm]
theorem antidiagonal_eq_map_powerset [DecidableEq α] (s : Multiset α) :
    s.antidiagonal = s.powerset.map fun t ↦ (s - t, t) := by
  induction' s using Multiset.induction_on with a s hs
  · simp only [antidiagonal_zero, powerset_zero, zero_tsub, map_singleton]
  · simp_rw [antidiagonal_cons, powerset_cons, map_add, hs, map_map, Function.comp, Prod.map_mk,
      id.def, sub_cons, erase_cons_head]
    rw [add_comm]
    

Proof state:
case cons
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
a : α
s : Multiset α
hs : antidiagonal s = map (fun t => (s - t, t)) (powerset s)
⊢ map (fun x => (a ::ₘ (s - x), x)) (powerset s) + map (fun x => (s - x, a ::ₘ x)) (powerset s) =
    map (fun x => (a ::ₘ s - x, x)) (powerset s) + map (fun x => (s - x, a ::ₘ x)) (powerset s)

Next tactic:
congr 1
theorem antidiagonal_eq_map_powerset [DecidableEq α] (s : Multiset α) :
    s.antidiagonal = s.powerset.map fun t ↦ (s - t, t) := by
  induction' s using Multiset.induction_on with a s hs
  · simp only [antidiagonal_zero, powerset_zero, zero_tsub, map_singleton]
  · simp_rw [antidiagonal_cons, powerset_cons, map_add, hs, map_map, Function.comp, Prod.map_mk,
      id.def, sub_cons, erase_cons_head]
    rw [add_comm]
    congr 1
    

Proof state:
case cons.e_a
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
a : α
s : Multiset α
hs : antidiagonal s = map (fun t => (s - t, t)) (powerset s)
⊢ map (fun x => (a ::ₘ (s - x), x)) (powerset s) = map (fun x => (a ::ₘ s - x, x)) (powerset s)

Next tactic:
refine' Multiset.map_congr rfl fun x hx ↦ _
theorem antidiagonal_eq_map_powerset [DecidableEq α] (s : Multiset α) :
    s.antidiagonal = s.powerset.map fun t ↦ (s - t, t) := by
  induction' s using Multiset.induction_on with a s hs
  · simp only [antidiagonal_zero, powerset_zero, zero_tsub, map_singleton]
  · simp_rw [antidiagonal_cons, powerset_cons, map_add, hs, map_map, Function.comp, Prod.map_mk,
      id.def, sub_cons, erase_cons_head]
    rw [add_comm]
    congr 1
    refine' Multiset.map_congr rfl fun x hx ↦ _
    

Proof state:
case cons.e_a
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
a : α
s : Multiset α
hs : antidiagonal s = map (fun t => (s - t, t)) (powerset s)
x : Multiset α
hx : x ∈ powerset s
⊢ (a ::ₘ (s - x), x) = (a ::ₘ s - x, x)

Next tactic:
rw [cons_sub_of_le _ (mem_powerset.mp hx)]
@[simp]
theorem card_antidiagonal (s : Multiset α) : card (antidiagonal s) = 2 ^ card s := by
  

Proof state:
α : Type u_1
β : Type u_2
s : Multiset α
⊢ card (antidiagonal s) = 2 ^ card s

Next tactic:
have := card_powerset s
@[simp]
theorem card_antidiagonal (s : Multiset α) : card (antidiagonal s) = 2 ^ card s := by
  have := card_powerset s
  

Proof state:
α : Type u_1
β : Type u_2
s : Multiset α
this : card (powerset s) = 2 ^ card s
⊢ card (antidiagonal s) = 2 ^ card s

Next tactic:
rwa [← antidiagonal_map_fst, card_map] at this
theorem prod_map_add [CommSemiring β] {s : Multiset α} {f g : α → β} :
    prod (s.map fun a ↦ f a + g a) =
      sum ((antidiagonal s).map fun p ↦ (p.1.map f).prod * (p.2.map g).prod) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : CommSemiring β
s : Multiset α
f g : α → β
⊢ prod (map (fun a => f a + g a) s) = sum (map (fun p => prod (map f p.1) * prod (map g p.2)) (antidiagonal s))

Next tactic:
refine' s.induction_on _ _
theorem prod_map_add [CommSemiring β] {s : Multiset α} {f g : α → β} :
    prod (s.map fun a ↦ f a + g a) =
      sum ((antidiagonal s).map fun p ↦ (p.1.map f).prod * (p.2.map g).prod) := by
  refine' s.induction_on _ _
  · 

Proof state:
case refine'_1
α : Type u_1
β : Type u_2
inst✝ : CommSemiring β
s : Multiset α
f g : α → β
⊢ prod (map (fun a => f a + g a) 0) = sum (map (fun p => prod (map f p.1) * prod (map g p.2)) (antidiagonal 0))

Next tactic:
simp only [map_zero, prod_zero, antidiagonal_zero, map_singleton, mul_one, sum_singleton]
theorem prod_map_add [CommSemiring β] {s : Multiset α} {f g : α → β} :
    prod (s.map fun a ↦ f a + g a) =
      sum ((antidiagonal s).map fun p ↦ (p.1.map f).prod * (p.2.map g).prod) := by
  refine' s.induction_on _ _
  · simp only [map_zero, prod_zero, antidiagonal_zero, map_singleton, mul_one, sum_singleton]
  · 

Proof state:
case refine'_2
α : Type u_1
β : Type u_2
inst✝ : CommSemiring β
s : Multiset α
f g : α → β
⊢ ∀ ⦃a : α⦄ {s : Multiset α},
    prod (map (fun a => f a + g a) s) = sum (map (fun p => prod (map f p.1) * prod (map g p.2)) (antidiagonal s)) →
      prod (map (fun a => f a + g a) (a ::ₘ s)) =
        sum (map (fun p => prod (map f p.1) * prod (map g p.2)) (antidiagonal (a ::ₘ s)))

Next tactic:
intro a s ih
theorem prod_map_add [CommSemiring β] {s : Multiset α} {f g : α → β} :
    prod (s.map fun a ↦ f a + g a) =
      sum ((antidiagonal s).map fun p ↦ (p.1.map f).prod * (p.2.map g).prod) := by
  refine' s.induction_on _ _
  · simp only [map_zero, prod_zero, antidiagonal_zero, map_singleton, mul_one, sum_singleton]
  · intro a s ih
    

Proof state:
case refine'_2
α : Type u_1
β : Type u_2
inst✝ : CommSemiring β
s✝ : Multiset α
f g : α → β
a : α
s : Multiset α
ih : prod (map (fun a => f a + g a) s) = sum (map (fun p => prod (map f p.1) * prod (map g p.2)) (antidiagonal s))
⊢ prod (map (fun a => f a + g a) (a ::ₘ s)) =
    sum (map (fun p => prod (map f p.1) * prod (map g p.2)) (antidiagonal (a ::ₘ s)))

Next tactic:
simp only [map_cons, prod_cons, ih, sum_map_mul_left.symm, add_mul, mul_left_comm (f a),
      mul_left_comm (g a), sum_map_add, antidiagonal_cons, Prod_map, id_eq, map_add, map_map,
      Function.comp_apply, mul_assoc, sum_add]
theorem prod_map_add [CommSemiring β] {s : Multiset α} {f g : α → β} :
    prod (s.map fun a ↦ f a + g a) =
      sum ((antidiagonal s).map fun p ↦ (p.1.map f).prod * (p.2.map g).prod) := by
  refine' s.induction_on _ _
  · simp only [map_zero, prod_zero, antidiagonal_zero, map_singleton, mul_one, sum_singleton]
  · intro a s ih
    simp only [map_cons, prod_cons, ih, sum_map_mul_left.symm, add_mul, mul_left_comm (f a),
      mul_left_comm (g a), sum_map_add, antidiagonal_cons, Prod_map, id_eq, map_add, map_map,
      Function.comp_apply, mul_assoc, sum_add]
    

Proof state:
case refine'_2
α : Type u_1
β : Type u_2
inst✝ : CommSemiring β
s✝ : Multiset α
f g : α → β
a : α
s : Multiset α
ih : prod (map (fun a => f a + g a) s) = sum (map (fun p => prod (map f p.1) * prod (map g p.2)) (antidiagonal s))
⊢ sum (map (fun i => prod (map f i.1) * (f a * prod (map g i.2))) (antidiagonal s)) +
      sum (map (fun i => prod (map f i.1) * (g a * prod (map g i.2))) (antidiagonal s)) =
    sum (map (fun x => prod (map f x.1) * (g a * prod (map g x.2))) (antidiagonal s)) +
      sum (map (fun i => prod (map f i.1) * (f a * prod (map g i.2))) (antidiagonal s))

Next tactic:
exact add_comm _ _
theorem smul_zero_mk {α : Type*} [Monoid M] [AddMonoid α] [DistribMulAction M α] (a : M) (c : β) :
    a • ((0 : α), c) = (0, a • c) := by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α✝ : Type u_5
β : Type u_6
inst✝⁶ : SMul M α✝
inst✝⁵ : SMul M β
inst✝⁴ : SMul N α✝
inst✝³ : SMul N β
a✝ : M
x : α✝ × β
α : Type u_7
inst✝² : Monoid M
inst✝¹ : AddMonoid α
inst✝ : DistribMulAction M α
a : M
c : β
⊢ a • (0, c) = (0, a • c)

Next tactic:
rw [Prod.smul_mk, smul_zero]
theorem smul_mk_zero {β : Type*} [Monoid M] [AddMonoid β] [DistribMulAction M β] (a : M) (b : α) :
    a • (b, (0 : β)) = (a • b, 0) := by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β✝ : Type u_6
inst✝⁶ : SMul M α
inst✝⁵ : SMul M β✝
inst✝⁴ : SMul N α
inst✝³ : SMul N β✝
a✝ : M
x : α × β✝
β : Type u_7
inst✝² : Monoid M
inst✝¹ : AddMonoid β
inst✝ : DistribMulAction M β
a : M
b : α
⊢ a • (b, 0) = (a • b, 0)

Next tactic:
rw [Prod.smul_mk, smul_zero]
@[to_additive]
instance faithfulSMulLeft [FaithfulSMul M α] [Nonempty β] : FaithfulSMul M (α × β) :=
  ⟨fun h =>
    let ⟨b⟩ := ‹Nonempty β›
    eq_of_smul_eq_smul fun a : α => by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝⁷ : SMul M α
inst✝⁶ : SMul M β
inst✝⁵ : SMul N α
inst✝⁴ : SMul N β
a✝ : M
x : α × β
inst✝³ : Pow α E
inst✝² : Pow β E
inst✝¹ : FaithfulSMul M α
inst✝ : Nonempty β
m₁✝ m₂✝ : M
h : ∀ (a : α × β), m₁✝ • a = m₂✝ • a
b : β
a : α
⊢ m₁✝ • a = m₂✝ • a

Next tactic:
injection h (a, b)
@[to_additive]
instance faithfulSMulRight [Nonempty α] [FaithfulSMul M β] : FaithfulSMul M (α × β) :=
  ⟨fun h =>
    let ⟨a⟩ := ‹Nonempty α›
    eq_of_smul_eq_smul fun b : β => by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝⁷ : SMul M α
inst✝⁶ : SMul M β
inst✝⁵ : SMul N α
inst✝⁴ : SMul N β
a✝ : M
x : α × β
inst✝³ : Pow α E
inst✝² : Pow β E
inst✝¹ : Nonempty α
inst✝ : FaithfulSMul M β
m₁✝ m₂✝ : M
h : ∀ (a : α × β), m₁✝ • a = m₂✝ • a
a : α
b : β
⊢ m₁✝ • b = m₂✝ • b

Next tactic:
injection h (a, b)
@[to_additive]
instance smulCommClassBoth [Mul N] [Mul P] [SMul M N] [SMul M P] [SMulCommClass M N N]
    [SMulCommClass M P P] : SMulCommClass M (N × P) (N × P) :=
  ⟨fun c x y => by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝⁵ : Mul N
inst✝⁴ : Mul P
inst✝³ : SMul M N
inst✝² : SMul M P
inst✝¹ : SMulCommClass M N N
inst✝ : SMulCommClass M P P
c : M
x y : N × P
⊢ c • x • y = x • c • y

Next tactic:
simp [smul_def, mul_def, mul_smul_comm]
instance isScalarTowerBoth [Mul N] [Mul P] [SMul M N] [SMul M P] [IsScalarTower M N N]
    [IsScalarTower M P P] : IsScalarTower M (N × P) (N × P) :=
  ⟨fun c x y => by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝⁵ : Mul N
inst✝⁴ : Mul P
inst✝³ : SMul M N
inst✝² : SMul M P
inst✝¹ : IsScalarTower M N N
inst✝ : IsScalarTower M P P
c : M
x y : N × P
⊢ (c • x) • y = c • x • y

Next tactic:
simp [smul_def, mul_def, smul_mul_assoc]
/-- Construct a `MulAction` by a product monoid from `MulAction`s by the factors.
  This is not an instance to avoid diamonds for example when `α := M × N`. -/
@[to_additive AddAction.prodOfVAddCommClass
  "Construct an `AddAction` by a product monoid from `AddAction`s by the factors.
  This is not an instance to avoid diamonds for example when `α := M × N`."]
abbrev MulAction.prodOfSMulCommClass [MulAction M α] [MulAction N α] [SMulCommClass M N α] :
    MulAction (M × N) α where
  smul mn a := mn.1 • mn.2 • a
  one_smul a := (one_smul M _).trans (one_smul N a)
  mul_smul x y a := by
    

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : MulAction M α
inst✝¹ : MulAction N α
inst✝ : SMulCommClass M N α
x y : M × N
a : α
⊢ (x * y) • a = x • y • a

Next tactic:
change (x.1 * y.1) • (x.2 * y.2) • a = x.1 • x.2 • y.1 • y.2 • a
/-- Construct a `MulAction` by a product monoid from `MulAction`s by the factors.
  This is not an instance to avoid diamonds for example when `α := M × N`. -/
@[to_additive AddAction.prodOfVAddCommClass
  "Construct an `AddAction` by a product monoid from `AddAction`s by the factors.
  This is not an instance to avoid diamonds for example when `α := M × N`."]
abbrev MulAction.prodOfSMulCommClass [MulAction M α] [MulAction N α] [SMulCommClass M N α] :
    MulAction (M × N) α where
  smul mn a := mn.1 • mn.2 • a
  one_smul a := (one_smul M _).trans (one_smul N a)
  mul_smul x y a := by
    change (x.1 * y.1) • (x.2 * y.2) • a = x.1 • x.2 • y.1 • y.2 • a
    

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : MulAction M α
inst✝¹ : MulAction N α
inst✝ : SMulCommClass M N α
x y : M × N
a : α
⊢ (x.1 * y.1) • (x.2 * y.2) • a = x.1 • x.2 • y.1 • y.2 • a

Next tactic:
rw [mul_smul, mul_smul, smul_comm y.1 x.2]
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
x✝ : MulAction (M × N) α
instM : MulAction M α := compHom α (MonoidHom.inl M N)
instN : MulAction N α := compHom α (MonoidHom.inr M N)
m : M
n : N
a : α
⊢ m • n • a = n • m • a

Next tactic:
change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
x✝ : MulAction (M × N) α
instM : MulAction M α := compHom α (MonoidHom.inl M N)
instN : MulAction N α := compHom α (MonoidHom.inr M N)
m : M
n : N
a : α
⊢ (m, 1) • (1, n) • a = (1, n) • (m, 1) • a

Next tactic:
simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul]
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul] }⟩
  invFun _insts :=
    letI := _insts.1; letI := _insts.2.1; have := _insts.2.2
    MulAction.prodOfSMulCommClass M N α
  left_inv := by
    

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
⊢ Function.LeftInverse
    (fun _insts =>
      let_fun this := (_ : SMulCommClass M N α);
      prodOfSMulCommClass M N α)
    fun x =>
    { fst := compHom α (MonoidHom.inl M N),
      snd := { fst := compHom α (MonoidHom.inr M N), snd := (_ : SMulCommClass M N α) } }

Next tactic:
rintro ⟨-, hsmul⟩
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul] }⟩
  invFun _insts :=
    letI := _insts.1; letI := _insts.2.1; have := _insts.2.2
    MulAction.prodOfSMulCommClass M N α
  left_inv := by
    rintro ⟨-, hsmul⟩; 

Proof state:
case mk
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
toSMul✝ : SMul (M × N) α
one_smul✝ : ∀ (b : α), 1 • b = b
hsmul : ∀ (x y : M × N) (b : α), (x * y) • b = x • y • b
⊢ (fun _insts =>
        let_fun this := (_ : SMulCommClass M N α);
        prodOfSMulCommClass M N α)
      ((fun x =>
          { fst := compHom α (MonoidHom.inl M N),
            snd := { fst := compHom α (MonoidHom.inr M N), snd := (_ : SMulCommClass M N α) } })
        (mk one_smul✝ hsmul)) =
    mk one_smul✝ hsmul

Next tactic:
dsimp only
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul] }⟩
  invFun _insts :=
    letI := _insts.1; letI := _insts.2.1; have := _insts.2.2
    MulAction.prodOfSMulCommClass M N α
  left_inv := by
    rintro ⟨-, hsmul⟩; dsimp only; 

Proof state:
case mk
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
toSMul✝ : SMul (M × N) α
one_smul✝ : ∀ (b : α), 1 • b = b
hsmul : ∀ (x y : M × N) (b : α), (x * y) • b = x • y • b
⊢ prodOfSMulCommClass M N α = mk one_smul✝ hsmul

Next tactic:
congr
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul] }⟩
  invFun _insts :=
    letI := _insts.1; letI := _insts.2.1; have := _insts.2.2
    MulAction.prodOfSMulCommClass M N α
  left_inv := by
    rintro ⟨-, hsmul⟩; dsimp only; congr; 

Proof state:
case mk
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
toSMul✝ : SMul (M × N) α
one_smul✝ : ∀ (b : α), 1 • b = b
hsmul : ∀ (x y : M × N) (b : α), (x * y) • b = x • y • b
⊢ prodOfSMulCommClass M N α = mk one_smul✝ hsmul

Next tactic:
ext ⟨m, n⟩ a
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul] }⟩
  invFun _insts :=
    letI := _insts.1; letI := _insts.2.1; have := _insts.2.2
    MulAction.prodOfSMulCommClass M N α
  left_inv := by
    rintro ⟨-, hsmul⟩; dsimp only; congr; ext ⟨m, n⟩ a
    

Proof state:
case mk.smul.h.mk.h
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
toSMul✝ : SMul (M × N) α
one_smul✝ : ∀ (b : α), 1 • b = b
hsmul : ∀ (x y : M × N) (b : α), (x * y) • b = x • y • b
m : M
n : N
a : α
⊢ SMul.smul (m, n) a = SMul.smul (m, n) a

Next tactic:
change (m, (1 : N)) • ((1 : M), n) • a = _
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul] }⟩
  invFun _insts :=
    letI := _insts.1; letI := _insts.2.1; have := _insts.2.2
    MulAction.prodOfSMulCommClass M N α
  left_inv := by
    rintro ⟨-, hsmul⟩; dsimp only; congr; ext ⟨m, n⟩ a
    change (m, (1 : N)) • ((1 : M), n) • a = _
    

Proof state:
case mk.smul.h.mk.h
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
toSMul✝ : SMul (M × N) α
one_smul✝ : ∀ (b : α), 1 • b = b
hsmul : ∀ (x y : M × N) (b : α), (x * y) • b = x • y • b
m : M
n : N
a : α
⊢ (m, 1) • (1, n) • a = SMul.smul (m, n) a

Next tactic:
rw [← hsmul, Prod.mk_mul_mk, mul_one, one_mul]
/-- A `MulAction` by a product monoid is equivalent to commuting `MulAction`s by the factors. -/
@[to_additive AddAction.prodEquiv "An `AddAction` by a product monoid is equivalent to
  commuting `AddAction`s by the factors."]
def MulAction.prodEquiv :
    MulAction (M × N) α ≃ Σ' (_ : MulAction M α) (_ : MulAction N α), SMulCommClass M N α where
  toFun _ :=
    letI instM := MulAction.compHom α (.inl M N)
    letI instN := MulAction.compHom α (.inr M N)
    ⟨instM, instN,
    { smul_comm := fun m n a ↦ by
        change (m, (1 : N)) • ((1 : M), n) • a = ((1 : M), n) • (m, (1 : N)) • a
        simp_rw [smul_smul, Prod.mk_mul_mk, mul_one, one_mul] }⟩
  invFun _insts :=
    letI := _insts.1; letI := _insts.2.1; have := _insts.2.2
    MulAction.prodOfSMulCommClass M N α
  left_inv := by
    rintro ⟨-, hsmul⟩; dsimp only; congr; ext ⟨m, n⟩ a
    change (m, (1 : N)) • ((1 : M), n) • a = _
    rw [← hsmul, Prod.mk_mul_mk, mul_one, one_mul]; 

Proof state:
case mk.smul.h.mk.h
M : Type u_1
N : Type u_2
P : Type u_3
E : Type u_4
α : Type u_5
β : Type u_6
inst✝¹ : Monoid M
inst✝ : Monoid N
toSMul✝ : SMul (M × N) α
one_smul✝ : ∀ (b : α), 1 • b = b
hsmul : ∀ (x y : M × N) (b : α), (x * y) • b = x • y • b
m : M
n : N
a : α
⊢ (m, n) • a = SMul.smul (m, n) a

Next tactic:
rfl