Module docstring
{"# Big operators on a list in rings
This file contains the results concerning the interaction of list big operators with rings. "}
{"# Big operators on a list in rings
This file contains the results concerning the interaction of list big operators with rings. "}
Commute.list_sum_right
      theorem
     (a : R) (l : List R) (h : ∀ b ∈ l, Commute a b) : Commute a l.sum
        lemma list_sum_right (a : R) (l : List R) (h : ∀ b ∈ l, Commute a b) : Commute a l.sum := by
  induction l with
  | nil => exact Commute.zero_right _
  | cons x xs ih =>
    rw [List.sum_cons]
    exact (h _ mem_cons_self).add_right (ih fun j hj ↦ h _ <| mem_cons_of_mem _ hj)
        Commute.list_sum_left
      theorem
     (b : R) (l : List R) (h : ∀ a ∈ l, Commute a b) : Commute l.sum b
        lemma list_sum_left (b : R) (l : List R) (h : ∀ a ∈ l, Commute a b) : Commute l.sum b :=
  ((Commute.list_sum_right _ _) fun _x hx ↦ (h _ hx).symm).symm
        List.prod_map_neg
      theorem
     (l : List M) : (l.map Neg.neg).prod = (-1) ^ l.length * l.prod
        
      List.prod_eq_zero
      theorem
     :
  ∀ {l : List M₀},
    (0 : M₀) ∈ l →
      l.prod =
        0
          -- |  absurd h (not_mem_nil _)
        /-- If zero is an element of a list `l`, then `List.prod l = 0`. If the domain is a nontrivial
monoid with zero with no divisors, then this implication becomes an `iff`, see
`List.prod_eq_zero_iff`. -/
lemma prod_eq_zero : ∀ {l : List M₀}, (0 : M₀) ∈ l → l.prod = 0
  -- |  absurd h (not_mem_nil _)
  | a :: l, h => by
    rw [prod_cons]
    rcases mem_cons.1 h with ha | hl
    exacts [mul_eq_zero_of_left ha.symm _, mul_eq_zero_of_right _ (prod_eq_zero hl)]
        List.prod_eq_zero_iff
      theorem
     : ∀ {l : List M₀}, l.prod = 0 ↔ (0 : M₀) ∈ l
        /-- Product of elements of a list `l` equals zero if and only if `0 ∈ l`. See also
`List.prod_eq_zero` for an implication that needs weaker typeclass assumptions. -/
@[simp] lemma prod_eq_zero_iff : ∀ {l : List M₀}, l.prod = 0 ↔ (0 : M₀) ∈ l
  | [] => by simp
  | a :: l => by rw [prod_cons, mul_eq_zero, prod_eq_zero_iff, mem_cons, eq_comm]
        List.prod_ne_zero
      theorem
     (hL : (0 : M₀) ∉ l) : l.prod ≠ 0
        lemma prod_ne_zero (hL : (0 : M₀) ∉ l) : l.prod ≠ 0 := mt prod_eq_zero_iff.1 hL
        List.sum_map_mul_left
      theorem
     : (l.map fun b ↦ r * f b).sum = r * (l.map f).sum
        lemma sum_map_mul_left : (l.map fun b ↦ r * f b).sum = r * (l.map f).sum :=
  sum_map_hom l f <| AddMonoidHom.mulLeft r
        List.sum_map_mul_right
      theorem
     : (l.map fun b ↦ f b * r).sum = (l.map f).sum * r
        lemma sum_map_mul_right : (l.map fun b ↦ f b * r).sum = (l.map f).sum * r :=
  sum_map_hom l f <| AddMonoidHom.mulRight r
        List.dvd_sum
      theorem
     [NonUnitalSemiring R] {a} {l : List R} (h : ∀ x ∈ l, a ∣ x) : a ∣ l.sum
        lemma dvd_sum [NonUnitalSemiring R] {a} {l : List R} (h : ∀ x ∈ l, a ∣ x) : a ∣ l.sum := by
  induction l with
  | nil => exact dvd_zero _
  | cons x l ih =>
    rw [List.sum_cons]
    exact dvd_add (h _ mem_cons_self) (ih fun x hx ↦ h x (mem_cons_of_mem _ hx))
        List.sum_zipWith_distrib_left
      theorem
     [NonUnitalNonAssocSemiring R] (f : ι → κ → R) (a : R) :
  ∀ (l₁ : List ι) (l₂ : List κ), (zipWith (fun i j ↦ a * f i j) l₁ l₂).sum = a * (zipWith f l₁ l₂).sum
        @[simp] lemma sum_zipWith_distrib_left [NonUnitalNonAssocSemiring R] (f : ι → κ → R) (a : R) :
    ∀ (l₁ : List ι) (l₂ : List κ),
      (zipWith (fun i j ↦ a * f i j) l₁ l₂).sum = a * (zipWith f l₁ l₂).sum
  | [], _ => by simp
  | _, [] => by simp
  | i :: l₁, j :: l₂ => by simp [sum_zipWith_distrib_left, mul_add]