/-- **Summation by parts**, also known as **Abel's lemma** or an **Abel transformation** -/
theorem sum_Ico_by_parts (hmn : m < n) :
    ∑ i in Ico m n, f i • g i =
      f (n - 1) • G n - f m • G m - ∑ i in Ico m (n - 1), (f (i + 1) - f i) • G (i + 1) := by
  have h₁ : (∑ i in Ico (m + 1) n, f i • G i) = ∑ i in Ico m (n - 1), f (i + 1) • G (i + 1) := by
    rw [← Nat.sub_add_cancel (Nat.one_le_of_lt hmn), ← sum_Ico_add']
    simp only [ge_iff_le, tsub_le_iff_right, add_le_iff_nonpos_left, nonpos_iff_eq_zero,
      tsub_eq_zero_iff_le, add_tsub_cancel_right]
  have h₂ :
    (∑ i in Ico (m + 1) n, f i • G (i + 1)) =
      (∑ i in Ico m (n - 1), f i • G (i + 1)) + f (n - 1) • G n - f m • G (m + 1) := by
    rw [← sum_Ico_sub_bot _ hmn, ← sum_Ico_succ_sub_top _ (Nat.le_sub_one_of_lt hmn),
      Nat.sub_add_cancel (pos_of_gt hmn), sub_add_cancel]
  rw [sum_eq_sum_Ico_succ_bot hmn]
  -- porting note: the following used to be done with `conv`
  have h₃: (Finset.sum (Ico (m + 1) n) fun i => f i • g i) =
             (Finset.sum (Ico (m + 1) n) fun i =>
                f i • ((Finset.sum (Finset.range (i + 1)) g) -
                        (Finset.sum (Finset.range i) g))) := by
    congr; funext; rw [← sum_range_succ_sub_sum g]
  rw [h₃]
  simp_rw [smul_sub, sum_sub_distrib, h₂, h₁]
  -- porting note: the following used to be done with `conv`
  have h₄ : ((((Finset.sum (Ico m (n - 1)) fun i => f i • Finset.sum (range (i + 1)) fun i => g i) +
      f (n - 1) • Finset.sum (range n) fun i => g i) -
      f m • Finset.sum (range (m + 1)) fun i => g i) -
      Finset.sum (Ico m (n - 1)) fun i => f (i + 1) • Finset.sum (range (i + 1)) fun i => g i) =
      f (n - 1) • (range n).sum g - f m • (range (m + 1)).sum g +
      Finset.sum (Ico m (n - 1)) (fun i => f i • (range (i + 1)).sum g -
      f (i + 1) • (range (i + 1)).sum g) := by
    rw [← add_sub, add_comm, ← add_sub, ← sum_sub_distrib]
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
f : ℕ → R
g : ℕ → M
m n : ℕ
hmn : m < n
h₁ : ∑ i in Ico (m + 1) n, f i • ∑ i in range i, g i = ∑ i in Ico m (n - 1), f (i + 1) • ∑ i in range (i + 1), g i
h₂ :
  ∑ i in Ico (m + 1) n, f i • ∑ i in range (i + 1), g i =
    ∑ i in Ico m (n - 1), f i • ∑ i in range (i + 1), g i + f (n - 1) • ∑ i in range n, g i -
      f m • ∑ i in range (m + 1), g i
h₃ :
  ∑ i in Ico (m + 1) n, f i • g i = ∑ i in Ico (m + 1) n, f i • (Finset.sum (range (i + 1)) g - Finset.sum (range i) g)
h₄ :
  ∑ i in Ico m (n - 1), f i • ∑ i in range (i + 1), g i + f (n - 1) • ∑ i in range n, g i -
        f m • ∑ i in range (m + 1), g i -
      ∑ i in Ico m (n - 1), f (i + 1) • ∑ i in range (i + 1), g i =
    f (n - 1) • Finset.sum (range n) g - f m • Finset.sum (range (m + 1)) g +
      ∑ i in Ico m (n - 1), (f i • Finset.sum (range (i + 1)) g - f (i + 1) • Finset.sum (range (i + 1)) g)
⊢ f m • g m +
      (∑ i in Ico m (n - 1), f i • ∑ i in range (i + 1), g i + f (n - 1) • ∑ i in range n, g i -
          f m • ∑ i in range (m + 1), g i -
        ∑ i in Ico m (n - 1), f (i + 1) • ∑ i in range (i + 1), g i) =
    f (n - 1) • ∑ i in range n, g i - f m • ∑ i in range m, g i -
      ∑ i in Ico m (n - 1), (f (i + 1) - f i) • ∑ i in range (i + 1), g i

Next tactic:
rw [h₄]