l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
instance monoid [∀ i, Monoid <| f i] : Monoid (∀ i : I, f i) :=
  { semigroup, mulOneClass with
    npow := fun n x i => x i ^ n
    --pi_instance
    npow_zero := by intros; ext; exact Monoid.npow_zero _
    npow_succ := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → Monoid (f i)
src✝¹ : Semigroup ((i : I) → f i) := semigroup
src✝ : MulOneClass ((i : I) → f i) := mulOneClass
n✝ : ℕ
x✝¹ : (i : I) → f i
x✝ : I
⊢ (fun n x i => x i ^ n) (n✝ + 1) x✝¹ x✝ = (x✝¹ * (fun n x i => x i ^ n) n✝ x✝¹) x✝

Next tactic:
exact Monoid.npow_succ _ _
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
⊢ ∀ (a b : (i : I) → f i), a / b = a * b⁻¹

Next tactic:
intros
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
a✝ b✝ : (i : I) → f i
⊢ a✝ / b✝ = a✝ * b✝⁻¹

Next tactic:
ext
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
a✝ b✝ : (i : I) → f i
x✝ : I
⊢ (a✝ / b✝) x✝ = (a✝ * b✝⁻¹) x✝

Next tactic:
exact div_eq_mul_inv _ _
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
⊢ ∀ (a : (i : I) → f i), (fun z x i => x i ^ z) 0 a = 1

Next tactic:
intros
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
a✝ : (i : I) → f i
⊢ (fun z x i => x i ^ z) 0 a✝ = 1

Next tactic:
ext
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
a✝ : (i : I) → f i
x✝ : I
⊢ (fun z x i => x i ^ z) 0 a✝ x✝ = OfNat.ofNat 1 x✝

Next tactic:
exact DivInvMonoid.zpow_zero' _
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; ext; exact DivInvMonoid.zpow_zero' _
    zpow_succ' := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
⊢ ∀ (n : ℕ) (a : (i : I) → f i),
    (fun z x i => x i ^ z) (Int.ofNat (Nat.succ n)) a = a * (fun z x i => x i ^ z) (Int.ofNat n) a

Next tactic:
intros
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; ext; exact DivInvMonoid.zpow_zero' _
    zpow_succ' := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
n✝ : ℕ
a✝ : (i : I) → f i
⊢ (fun z x i => x i ^ z) (Int.ofNat (Nat.succ n✝)) a✝ = a✝ * (fun z x i => x i ^ z) (Int.ofNat n✝) a✝

Next tactic:
ext
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; ext; exact DivInvMonoid.zpow_zero' _
    zpow_succ' := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
n✝ : ℕ
a✝ : (i : I) → f i
x✝ : I
⊢ (fun z x i => x i ^ z) (Int.ofNat (Nat.succ n✝)) a✝ x✝ = (a✝ * (fun z x i => x i ^ z) (Int.ofNat n✝) a✝) x✝

Next tactic:
exact DivInvMonoid.zpow_succ' _ _
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; ext; exact DivInvMonoid.zpow_zero' _
    zpow_succ' := by intros; ext; exact DivInvMonoid.zpow_succ' _ _
    zpow_neg' := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
⊢ ∀ (n : ℕ) (a : (i : I) → f i), (fun z x i => x i ^ z) (Int.negSucc n) a = ((fun z x i => x i ^ z) (↑(Nat.succ n)) a)⁻¹

Next tactic:
intros
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; ext; exact DivInvMonoid.zpow_zero' _
    zpow_succ' := by intros; ext; exact DivInvMonoid.zpow_succ' _ _
    zpow_neg' := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
n✝ : ℕ
a✝ : (i : I) → f i
⊢ (fun z x i => x i ^ z) (Int.negSucc n✝) a✝ = ((fun z x i => x i ^ z) (↑(Nat.succ n✝)) a✝)⁻¹

Next tactic:
ext
@[to_additive Pi.subNegMonoid]
instance divInvMonoid [∀ i, DivInvMonoid <| f i] : DivInvMonoid (∀ i : I, f i) :=
  { monoid with
    inv := Inv.inv
    div := Div.div
    zpow := fun z x i => x i ^ z
    --pi_instance
    div_eq_mul_inv := by intros; ext; exact div_eq_mul_inv _ _
    zpow_zero' := by intros; ext; exact DivInvMonoid.zpow_zero' _
    zpow_succ' := by intros; ext; exact DivInvMonoid.zpow_succ' _ _
    zpow_neg' := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvMonoid (f i)
src✝ : Monoid ((i : I) → f i) := monoid
n✝ : ℕ
a✝ : (i : I) → f i
x✝ : I
⊢ (fun z x i => x i ^ z) (Int.negSucc n✝) a✝ x✝ = ((fun z x i => x i ^ z) (↑(Nat.succ n✝)) a✝)⁻¹ x✝

Next tactic:
exact DivInvMonoid.zpow_neg' _ _
@[to_additive Pi.subNegZeroMonoid]
instance divInvOneMonoid [∀ i, DivInvOneMonoid <| f i] : DivInvOneMonoid (∀ i : I, f i) :=
  { divInvMonoid with
    inv_one := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvOneMonoid (f i)
src✝ : DivInvMonoid ((i : I) → f i) := divInvMonoid
⊢ 1⁻¹ = 1

Next tactic:
ext
@[to_additive Pi.subNegZeroMonoid]
instance divInvOneMonoid [∀ i, DivInvOneMonoid <| f i] : DivInvOneMonoid (∀ i : I, f i) :=
  { divInvMonoid with
    inv_one := by ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivInvOneMonoid (f i)
src✝ : DivInvMonoid ((i : I) → f i) := divInvMonoid
x✝ : I
⊢ 1⁻¹ x✝ = OfNat.ofNat 1 x✝

Next tactic:
exact inv_one
@[to_additive]
instance involutiveInv [∀ i, InvolutiveInv <| f i] : InvolutiveInv (∀ i, f i) :=
  { inv := Inv.inv
    --pi_instance
    inv_inv := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → InvolutiveInv (f i)
⊢ ∀ (x : (i : I) → f i), x⁻¹⁻¹ = x

Next tactic:
intros
@[to_additive]
instance involutiveInv [∀ i, InvolutiveInv <| f i] : InvolutiveInv (∀ i, f i) :=
  { inv := Inv.inv
    --pi_instance
    inv_inv := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → InvolutiveInv (f i)
x✝ : (i : I) → f i
⊢ x✝⁻¹⁻¹ = x✝

Next tactic:
ext
@[to_additive]
instance involutiveInv [∀ i, InvolutiveInv <| f i] : InvolutiveInv (∀ i, f i) :=
  { inv := Inv.inv
    --pi_instance
    inv_inv := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → InvolutiveInv (f i)
x✝¹ : (i : I) → f i
x✝ : I
⊢ x✝¹⁻¹⁻¹ x✝ = x✝¹ x✝

Next tactic:
exact inv_inv _
@[to_additive Pi.subtractionMonoid]
instance divisionMonoid [∀ i, DivisionMonoid <| f i] : DivisionMonoid (∀ i, f i) :=
  { divInvMonoid, involutiveInv with
    --pi_instance
    mul_inv_rev := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivisionMonoid (f i)
src✝¹ : DivInvMonoid ((i : I) → f i) := divInvMonoid
src✝ : InvolutiveInv ((i : I) → f i) := involutiveInv
⊢ ∀ (a b : (i : I) → f i), (a * b)⁻¹ = b⁻¹ * a⁻¹

Next tactic:
intros
@[to_additive Pi.subtractionMonoid]
instance divisionMonoid [∀ i, DivisionMonoid <| f i] : DivisionMonoid (∀ i, f i) :=
  { divInvMonoid, involutiveInv with
    --pi_instance
    mul_inv_rev := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivisionMonoid (f i)
src✝¹ : DivInvMonoid ((i : I) → f i) := divInvMonoid
src✝ : InvolutiveInv ((i : I) → f i) := involutiveInv
a✝ b✝ : (i : I) → f i
⊢ (a✝ * b✝)⁻¹ = b✝⁻¹ * a✝⁻¹

Next tactic:
ext
@[to_additive Pi.subtractionMonoid]
instance divisionMonoid [∀ i, DivisionMonoid <| f i] : DivisionMonoid (∀ i, f i) :=
  { divInvMonoid, involutiveInv with
    --pi_instance
    mul_inv_rev := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivisionMonoid (f i)
src✝¹ : DivInvMonoid ((i : I) → f i) := divInvMonoid
src✝ : InvolutiveInv ((i : I) → f i) := involutiveInv
a✝ b✝ : (i : I) → f i
x✝ : I
⊢ (a✝ * b✝)⁻¹ x✝ = (b✝⁻¹ * a✝⁻¹) x✝

Next tactic:
exact mul_inv_rev _ _
@[to_additive Pi.subtractionMonoid]
instance divisionMonoid [∀ i, DivisionMonoid <| f i] : DivisionMonoid (∀ i, f i) :=
  { divInvMonoid, involutiveInv with
    --pi_instance
    mul_inv_rev := by intros; ext; exact mul_inv_rev _ _
    inv_eq_of_mul := by
      

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivisionMonoid (f i)
src✝¹ : DivInvMonoid ((i : I) → f i) := divInvMonoid
src✝ : InvolutiveInv ((i : I) → f i) := involutiveInv
⊢ ∀ (a b : (i : I) → f i), a * b = 1 → a⁻¹ = b

Next tactic:
intros _ _ h
@[to_additive Pi.subtractionMonoid]
instance divisionMonoid [∀ i, DivisionMonoid <| f i] : DivisionMonoid (∀ i, f i) :=
  { divInvMonoid, involutiveInv with
    --pi_instance
    mul_inv_rev := by intros; ext; exact mul_inv_rev _ _
    inv_eq_of_mul := by
      intros _ _ h; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivisionMonoid (f i)
src✝¹ : DivInvMonoid ((i : I) → f i) := divInvMonoid
src✝ : InvolutiveInv ((i : I) → f i) := involutiveInv
a✝ b✝ : (i : I) → f i
h : a✝ * b✝ = 1
⊢ a✝⁻¹ = b✝

Next tactic:
ext
@[to_additive Pi.subtractionMonoid]
instance divisionMonoid [∀ i, DivisionMonoid <| f i] : DivisionMonoid (∀ i, f i) :=
  { divInvMonoid, involutiveInv with
    --pi_instance
    mul_inv_rev := by intros; ext; exact mul_inv_rev _ _
    inv_eq_of_mul := by
      intros _ _ h; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → DivisionMonoid (f i)
src✝¹ : DivInvMonoid ((i : I) → f i) := divInvMonoid
src✝ : InvolutiveInv ((i : I) → f i) := involutiveInv
a✝ b✝ : (i : I) → f i
h : a✝ * b✝ = 1
x✝ : I
⊢ a✝⁻¹ x✝ = b✝ x✝

Next tactic:
exact DivisionMonoid.inv_eq_of_mul _ _ (congrFun h _)
@[to_additive]
instance group [∀ i, Group <| f i] : Group (∀ i : I, f i) :=
  { divInvMonoid with
    --pi_instance
    mul_left_inv := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → Group (f i)
src✝ : DivInvMonoid ((i : I) → f i) := divInvMonoid
⊢ ∀ (a : (i : I) → f i), a⁻¹ * a = 1

Next tactic:
intros
@[to_additive]
instance group [∀ i, Group <| f i] : Group (∀ i : I, f i) :=
  { divInvMonoid with
    --pi_instance
    mul_left_inv := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → Group (f i)
src✝ : DivInvMonoid ((i : I) → f i) := divInvMonoid
a✝ : (i : I) → f i
⊢ a✝⁻¹ * a✝ = 1

Next tactic:
ext
@[to_additive]
instance group [∀ i, Group <| f i] : Group (∀ i : I, f i) :=
  { divInvMonoid with
    --pi_instance
    mul_left_inv := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → Group (f i)
src✝ : DivInvMonoid ((i : I) → f i) := divInvMonoid
a✝ : (i : I) → f i
x✝ : I
⊢ (a✝⁻¹ * a✝) x✝ = OfNat.ofNat 1 x✝

Next tactic:
exact mul_left_inv _
instance mulZeroClass [∀ i, MulZeroClass <| f i] : MulZeroClass (∀ i : I, f i) :=
  { zero := (0 : ∀ i, f i)
    mul := (· * ·)
    --pi_instance
    zero_mul := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → MulZeroClass (f i)
⊢ ∀ (a : (i : I) → f i), 0 * a = 0

Next tactic:
intros
instance mulZeroClass [∀ i, MulZeroClass <| f i] : MulZeroClass (∀ i : I, f i) :=
  { zero := (0 : ∀ i, f i)
    mul := (· * ·)
    --pi_instance
    zero_mul := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → MulZeroClass (f i)
a✝ : (i : I) → f i
⊢ 0 * a✝ = 0

Next tactic:
ext
instance mulZeroClass [∀ i, MulZeroClass <| f i] : MulZeroClass (∀ i : I, f i) :=
  { zero := (0 : ∀ i, f i)
    mul := (· * ·)
    --pi_instance
    zero_mul := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → MulZeroClass (f i)
a✝ : (i : I) → f i
x✝ : I
⊢ (0 * a✝) x✝ = OfNat.ofNat 0 x✝

Next tactic:
exact zero_mul _
instance mulZeroClass [∀ i, MulZeroClass <| f i] : MulZeroClass (∀ i : I, f i) :=
  { zero := (0 : ∀ i, f i)
    mul := (· * ·)
    --pi_instance
    zero_mul := by intros; ext; exact zero_mul _
    mul_zero := by 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → MulZeroClass (f i)
⊢ ∀ (a : (i : I) → f i), a * 0 = 0

Next tactic:
intros
instance mulZeroClass [∀ i, MulZeroClass <| f i] : MulZeroClass (∀ i : I, f i) :=
  { zero := (0 : ∀ i, f i)
    mul := (· * ·)
    --pi_instance
    zero_mul := by intros; ext; exact zero_mul _
    mul_zero := by intros; 

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → MulZeroClass (f i)
a✝ : (i : I) → f i
⊢ a✝ * 0 = 0

Next tactic:
ext
instance mulZeroClass [∀ i, MulZeroClass <| f i] : MulZeroClass (∀ i : I, f i) :=
  { zero := (0 : ∀ i, f i)
    mul := (· * ·)
    --pi_instance
    zero_mul := by intros; ext; exact zero_mul _
    mul_zero := by intros; ext; 

Proof state:
case h
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝ : (i : I) → MulZeroClass (f i)
a✝ : (i : I) → f i
x✝ : I
⊢ (a✝ * 0) x✝ = OfNat.ofNat 0 x✝

Next tactic:
exact mul_zero _
/-- Semigroup homomorphism between the function spaces `I → α` and `I → β`, induced by a semigroup
homomorphism `f` between `α` and `β`. -/
@[to_additive (attr := simps) "Additive semigroup homomorphism between the function spaces `I → α`
and `I → β`, induced by an additive semigroup homomorphism `f` between `α` and `β`"]
protected def MulHom.compLeft {α β : Type*} [Mul α] [Mul β] (f : α →ₙ* β) (I : Type*) :
    (I → α) →ₙ* I → β where
  toFun h := f ∘ h
  map_mul' _ _ := by 

Proof state:
ι : Type u_1
α✝ : Type u_2
I✝ : Type u
f✝ : I✝ → Type v
x y : (i : I✝) → f✝ i
i j : I✝
inst✝² : (i : I✝) → Mul (f✝ i)
α : Type u_3
β : Type u_4
inst✝¹ : Mul α
inst✝ : Mul β
f : α →ₙ* β
I : Type u_5
x✝¹ x✝ : I → α
⊢ (fun h => ⇑f ∘ h) (x✝¹ * x✝) = (fun h => ⇑f ∘ h) x✝¹ * (fun h => ⇑f ∘ h) x✝

Next tactic:
ext
/-- Semigroup homomorphism between the function spaces `I → α` and `I → β`, induced by a semigroup
homomorphism `f` between `α` and `β`. -/
@[to_additive (attr := simps) "Additive semigroup homomorphism between the function spaces `I → α`
and `I → β`, induced by an additive semigroup homomorphism `f` between `α` and `β`"]
protected def MulHom.compLeft {α β : Type*} [Mul α] [Mul β] (f : α →ₙ* β) (I : Type*) :
    (I → α) →ₙ* I → β where
  toFun h := f ∘ h
  map_mul' _ _ := by ext; 

Proof state:
case h
ι : Type u_1
α✝ : Type u_2
I✝ : Type u
f✝ : I✝ → Type v
x y : (i : I✝) → f✝ i
i j : I✝
inst✝² : (i : I✝) → Mul (f✝ i)
α : Type u_3
β : Type u_4
inst✝¹ : Mul α
inst✝ : Mul β
f : α →ₙ* β
I : Type u_5
x✝² x✝¹ : I → α
x✝ : I
⊢ (fun h => ⇑f ∘ h) (x✝² * x✝¹) x✝ = ((fun h => ⇑f ∘ h) x✝² * (fun h => ⇑f ∘ h) x✝¹) x✝

Next tactic:
simp
/-- Monoid homomorphism between the function spaces `I → α` and `I → β`, induced by a monoid
homomorphism `f` between `α` and `β`. -/
@[to_additive (attr := simps)
  "Additive monoid homomorphism between the function spaces `I → α` and `I → β`, induced by an
  additive monoid homomorphism `f` between `α` and `β`"]
protected def MonoidHom.compLeft {α β : Type*} [MulOneClass α] [MulOneClass β] (f : α →* β)
    (I : Type*) : (I → α) →* I → β where
  toFun h := f ∘ h
  map_one' := by 

Proof state:
ι : Type u_1
α✝ : Type u_2
I✝ : Type u
f✝ : I✝ → Type v
x y : (i : I✝) → f✝ i
i j : I✝
inst✝² : (i : I✝) → MulOneClass (f✝ i)
α : Type u_3
β : Type u_4
inst✝¹ : MulOneClass α
inst✝ : MulOneClass β
f : α →* β
I : Type u_5
⊢ (fun h => ⇑f ∘ h) 1 = 1

Next tactic:
ext
/-- Monoid homomorphism between the function spaces `I → α` and `I → β`, induced by a monoid
homomorphism `f` between `α` and `β`. -/
@[to_additive (attr := simps)
  "Additive monoid homomorphism between the function spaces `I → α` and `I → β`, induced by an
  additive monoid homomorphism `f` between `α` and `β`"]
protected def MonoidHom.compLeft {α β : Type*} [MulOneClass α] [MulOneClass β] (f : α →* β)
    (I : Type*) : (I → α) →* I → β where
  toFun h := f ∘ h
  map_one' := by ext; 

Proof state:
case h
ι : Type u_1
α✝ : Type u_2
I✝ : Type u
f✝ : I✝ → Type v
x y : (i : I✝) → f✝ i
i j : I✝
inst✝² : (i : I✝) → MulOneClass (f✝ i)
α : Type u_3
β : Type u_4
inst✝¹ : MulOneClass α
inst✝ : MulOneClass β
f : α →* β
I : Type u_5
x✝ : I
⊢ (fun h => ⇑f ∘ h) 1 x✝ = OfNat.ofNat 1 x✝

Next tactic:
dsimp
/-- Monoid homomorphism between the function spaces `I → α` and `I → β`, induced by a monoid
homomorphism `f` between `α` and `β`. -/
@[to_additive (attr := simps)
  "Additive monoid homomorphism between the function spaces `I → α` and `I → β`, induced by an
  additive monoid homomorphism `f` between `α` and `β`"]
protected def MonoidHom.compLeft {α β : Type*} [MulOneClass α] [MulOneClass β] (f : α →* β)
    (I : Type*) : (I → α) →* I → β where
  toFun h := f ∘ h
  map_one' := by ext; dsimp; 

Proof state:
case h
ι : Type u_1
α✝ : Type u_2
I✝ : Type u
f✝ : I✝ → Type v
x y : (i : I✝) → f✝ i
i j : I✝
inst✝² : (i : I✝) → MulOneClass (f✝ i)
α : Type u_3
β : Type u_4
inst✝¹ : MulOneClass α
inst✝ : MulOneClass β
f : α →* β
I : Type u_5
x✝ : I
⊢ f 1 = 1

Next tactic:
simp
/-- Monoid homomorphism between the function spaces `I → α` and `I → β`, induced by a monoid
homomorphism `f` between `α` and `β`. -/
@[to_additive (attr := simps)
  "Additive monoid homomorphism between the function spaces `I → α` and `I → β`, induced by an
  additive monoid homomorphism `f` between `α` and `β`"]
protected def MonoidHom.compLeft {α β : Type*} [MulOneClass α] [MulOneClass β] (f : α →* β)
    (I : Type*) : (I → α) →* I → β where
  toFun h := f ∘ h
  map_one' := by ext; dsimp; simp
  map_mul' _ _ := by 

Proof state:
ι : Type u_1
α✝ : Type u_2
I✝ : Type u
f✝ : I✝ → Type v
x y : (i : I✝) → f✝ i
i j : I✝
inst✝² : (i : I✝) → MulOneClass (f✝ i)
α : Type u_3
β : Type u_4
inst✝¹ : MulOneClass α
inst✝ : MulOneClass β
f : α →* β
I : Type u_5
x✝¹ x✝ : I → α
⊢ OneHom.toFun { toFun := fun h => ⇑f ∘ h, map_one' := (_ : (fun h => ⇑f ∘ h) 1 = 1) } (x✝¹ * x✝) =
    OneHom.toFun { toFun := fun h => ⇑f ∘ h, map_one' := (_ : (fun h => ⇑f ∘ h) 1 = 1) } x✝¹ *
      OneHom.toFun { toFun := fun h => ⇑f ∘ h, map_one' := (_ : (fun h => ⇑f ∘ h) 1 = 1) } x✝

Next tactic:
ext
/-- Monoid homomorphism between the function spaces `I → α` and `I → β`, induced by a monoid
homomorphism `f` between `α` and `β`. -/
@[to_additive (attr := simps)
  "Additive monoid homomorphism between the function spaces `I → α` and `I → β`, induced by an
  additive monoid homomorphism `f` between `α` and `β`"]
protected def MonoidHom.compLeft {α β : Type*} [MulOneClass α] [MulOneClass β] (f : α →* β)
    (I : Type*) : (I → α) →* I → β where
  toFun h := f ∘ h
  map_one' := by ext; dsimp; simp
  map_mul' _ _ := by ext; 

Proof state:
case h
ι : Type u_1
α✝ : Type u_2
I✝ : Type u
f✝ : I✝ → Type v
x y : (i : I✝) → f✝ i
i j : I✝
inst✝² : (i : I✝) → MulOneClass (f✝ i)
α : Type u_3
β : Type u_4
inst✝¹ : MulOneClass α
inst✝ : MulOneClass β
f : α →* β
I : Type u_5
x✝² x✝¹ : I → α
x✝ : I
⊢ OneHom.toFun { toFun := fun h => ⇑f ∘ h, map_one' := (_ : (fun h => ⇑f ∘ h) 1 = 1) } (x✝² * x✝¹) x✝ =
    (OneHom.toFun { toFun := fun h => ⇑f ∘ h, map_one' := (_ : (fun h => ⇑f ∘ h) 1 = 1) } x✝² *
        OneHom.toFun { toFun := fun h => ⇑f ∘ h, map_one' := (_ : (fun h => ⇑f ∘ h) 1 = 1) } x✝¹)
      x✝

Next tactic:
simp
/-- The injection into a pi group at different indices commutes.

For injections of commuting elements at the same index, see `Commute.map` -/
@[to_additive
      "The injection into an additive pi group at different indices commutes.

      For injections of commuting elements at the same index, see `AddCommute.map`"]
theorem Pi.mulSingle_commute [∀ i, MulOneClass <| f i] :
    Pairwise fun i j => ∀ (x : f i) (y : f j), Commute (mulSingle i x) (mulSingle j y) := by
  

Proof state:
ι : Type u_1
α : Type u_2
I : Type u
f : I → Type v
x y : (i : I) → f i
i j : I
inst✝¹ : DecidableEq I
inst✝ : (i : I) → MulOneClass (f i)
⊢ Pairwise fun i j => ∀ (x : f i) (y : f j), Commute (mulSingle i x) (mulSingle j y)

Next tactic:
intro i j hij x y