l3lab/ntp-mathlib huggingface dataset:
/-- Alternate form of **Faulhaber's theorem**, relating the sum of p-th powers to the Bernoulli
numbers: $$\sum_{k=1}^{n} k^p = \sum_{i=0}^p (-1)^iB_i\binom{p+1}{i}\frac{n^{p+1-i}}{p+1}.$$
Deduced from `sum_range_pow`. -/
theorem sum_Ico_pow (n p : ℕ) :
    (∑ k in Ico 1 (n + 1), (k : ℚ) ^ p) =
      ∑ i in range (p + 1), bernoulli' i * (p + 1).choose i * (n : ℚ) ^ (p + 1 - i) / (p + 1) := by
  rw [← Nat.cast_succ]
  -- dispose of the trivial case
  cases' p with p p
  · simp
  let f i := bernoulli i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  let f' i := bernoulli' i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  suffices (∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ i in range p.succ.succ, f' i by convert this
  -- prove some algebraic facts that will make things easier for us later on
  have hle := Nat.le_add_left 1 n
  have hne : (p + 1 + 1 : ℚ) ≠ 0 := by norm_cast; exact succ_ne_zero p.succ
  have h1 : ∀ r : ℚ, r * (p + 1 + 1) * (n : ℚ) ^ p.succ / (p + 1 + 1 : ℚ) = r * (n : ℚ) ^ p.succ :=
      fun r => by rw [mul_div_right_comm, mul_div_cancel _ hne]
  have h2 : f 1 + (n : ℚ) ^ p.succ = 1 / 2 * (n : ℚ) ^ p.succ := by
    simp_rw [bernoulli_one, choose_one_right, succ_sub_succ_eq_sub, cast_succ, tsub_zero, h1]
    ring
  have :
    (∑ i in range p, bernoulli (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2)) =
      ∑ i in range p, bernoulli' (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2) :=
    sum_congr rfl fun i _ => by rw [bernoulli_eq_bernoulli'_of_ne_one (succ_succ_ne_one i)]
  calc
    (-- replace sum over `Ico` with sum over `range` and simplify
        ∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ k in range n.succ, (k : ℚ) ^ p.succ :=
      by simp [sum_Ico_eq_sub _ hle, succ_ne_zero]
    -- extract the last term of the sum
        _ = (∑ k in range n, (k : ℚ) ^ p.succ) + (n : ℚ) ^ p.succ :=
      by 

Proof state:
A : Type u_1
inst✝¹ : CommRing A
inst✝ : Algebra ℚ A
n p : ℕ
f : ℕ → ℚ := fun i => bernoulli i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
f' : ℕ → ℚ := fun i => bernoulli' i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
hle : 1 ≤ n + 1
hne : ↑p + 1 + 1 ≠ 0
h1 : ∀ (r : ℚ), r * (↑p + 1 + 1) * ↑n ^ succ p / (↑p + 1 + 1) = r * ↑n ^ succ p
h2 : f 1 + ↑n ^ succ p = 1 / 2 * ↑n ^ succ p
this :
  ∑ i in range p, bernoulli (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2) =
    ∑ i in range p, bernoulli' (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2)
⊢ ∑ k in range (succ n), ↑k ^ succ p = ∑ k in range n, ↑k ^ succ p + ↑n ^ succ p

Next tactic:
rw [sum_range_succ]
/-- Alternate form of **Faulhaber's theorem**, relating the sum of p-th powers to the Bernoulli
numbers: $$\sum_{k=1}^{n} k^p = \sum_{i=0}^p (-1)^iB_i\binom{p+1}{i}\frac{n^{p+1-i}}{p+1}.$$
Deduced from `sum_range_pow`. -/
theorem sum_Ico_pow (n p : ℕ) :
    (∑ k in Ico 1 (n + 1), (k : ℚ) ^ p) =
      ∑ i in range (p + 1), bernoulli' i * (p + 1).choose i * (n : ℚ) ^ (p + 1 - i) / (p + 1) := by
  rw [← Nat.cast_succ]
  -- dispose of the trivial case
  cases' p with p p
  · simp
  let f i := bernoulli i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  let f' i := bernoulli' i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  suffices (∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ i in range p.succ.succ, f' i by convert this
  -- prove some algebraic facts that will make things easier for us later on
  have hle := Nat.le_add_left 1 n
  have hne : (p + 1 + 1 : ℚ) ≠ 0 := by norm_cast; exact succ_ne_zero p.succ
  have h1 : ∀ r : ℚ, r * (p + 1 + 1) * (n : ℚ) ^ p.succ / (p + 1 + 1 : ℚ) = r * (n : ℚ) ^ p.succ :=
      fun r => by rw [mul_div_right_comm, mul_div_cancel _ hne]
  have h2 : f 1 + (n : ℚ) ^ p.succ = 1 / 2 * (n : ℚ) ^ p.succ := by
    simp_rw [bernoulli_one, choose_one_right, succ_sub_succ_eq_sub, cast_succ, tsub_zero, h1]
    ring
  have :
    (∑ i in range p, bernoulli (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2)) =
      ∑ i in range p, bernoulli' (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2) :=
    sum_congr rfl fun i _ => by rw [bernoulli_eq_bernoulli'_of_ne_one (succ_succ_ne_one i)]
  calc
    (-- replace sum over `Ico` with sum over `range` and simplify
        ∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ k in range n.succ, (k : ℚ) ^ p.succ :=
      by simp [sum_Ico_eq_sub _ hle, succ_ne_zero]
    -- extract the last term of the sum
        _ = (∑ k in range n, (k : ℚ) ^ p.succ) + (n : ℚ) ^ p.succ :=
      by rw [sum_range_succ]
    -- apply the key lemma, `sum_range_pow`
        _ = (∑ i in range p.succ.succ, f i) + (n : ℚ) ^ p.succ :=
      by 

Proof state:
A : Type u_1
inst✝¹ : CommRing A
inst✝ : Algebra ℚ A
n p : ℕ
f : ℕ → ℚ := fun i => bernoulli i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
f' : ℕ → ℚ := fun i => bernoulli' i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
hle : 1 ≤ n + 1
hne : ↑p + 1 + 1 ≠ 0
h1 : ∀ (r : ℚ), r * (↑p + 1 + 1) * ↑n ^ succ p / (↑p + 1 + 1) = r * ↑n ^ succ p
h2 : f 1 + ↑n ^ succ p = 1 / 2 * ↑n ^ succ p
this :
  ∑ i in range p, bernoulli (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2) =
    ∑ i in range p, bernoulli' (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2)
⊢ ∑ k in range n, ↑k ^ succ p + ↑n ^ succ p = ∑ i in range (succ (succ p)), f i + ↑n ^ succ p

Next tactic:
simp [sum_range_pow]
/-- Alternate form of **Faulhaber's theorem**, relating the sum of p-th powers to the Bernoulli
numbers: $$\sum_{k=1}^{n} k^p = \sum_{i=0}^p (-1)^iB_i\binom{p+1}{i}\frac{n^{p+1-i}}{p+1}.$$
Deduced from `sum_range_pow`. -/
theorem sum_Ico_pow (n p : ℕ) :
    (∑ k in Ico 1 (n + 1), (k : ℚ) ^ p) =
      ∑ i in range (p + 1), bernoulli' i * (p + 1).choose i * (n : ℚ) ^ (p + 1 - i) / (p + 1) := by
  rw [← Nat.cast_succ]
  -- dispose of the trivial case
  cases' p with p p
  · simp
  let f i := bernoulli i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  let f' i := bernoulli' i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  suffices (∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ i in range p.succ.succ, f' i by convert this
  -- prove some algebraic facts that will make things easier for us later on
  have hle := Nat.le_add_left 1 n
  have hne : (p + 1 + 1 : ℚ) ≠ 0 := by norm_cast; exact succ_ne_zero p.succ
  have h1 : ∀ r : ℚ, r * (p + 1 + 1) * (n : ℚ) ^ p.succ / (p + 1 + 1 : ℚ) = r * (n : ℚ) ^ p.succ :=
      fun r => by rw [mul_div_right_comm, mul_div_cancel _ hne]
  have h2 : f 1 + (n : ℚ) ^ p.succ = 1 / 2 * (n : ℚ) ^ p.succ := by
    simp_rw [bernoulli_one, choose_one_right, succ_sub_succ_eq_sub, cast_succ, tsub_zero, h1]
    ring
  have :
    (∑ i in range p, bernoulli (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2)) =
      ∑ i in range p, bernoulli' (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2) :=
    sum_congr rfl fun i _ => by rw [bernoulli_eq_bernoulli'_of_ne_one (succ_succ_ne_one i)]
  calc
    (-- replace sum over `Ico` with sum over `range` and simplify
        ∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ k in range n.succ, (k : ℚ) ^ p.succ :=
      by simp [sum_Ico_eq_sub _ hle, succ_ne_zero]
    -- extract the last term of the sum
        _ = (∑ k in range n, (k : ℚ) ^ p.succ) + (n : ℚ) ^ p.succ :=
      by rw [sum_range_succ]
    -- apply the key lemma, `sum_range_pow`
        _ = (∑ i in range p.succ.succ, f i) + (n : ℚ) ^ p.succ :=
      by simp [sum_range_pow]
    -- extract the first two terms of the sum
        _ = (∑ i in range p, f i.succ.succ) + f 1 + f 0 + (n : ℚ) ^ p.succ :=
      by 

Proof state:
A : Type u_1
inst✝¹ : CommRing A
inst✝ : Algebra ℚ A
n p : ℕ
f : ℕ → ℚ := fun i => bernoulli i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
f' : ℕ → ℚ := fun i => bernoulli' i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
hle : 1 ≤ n + 1
hne : ↑p + 1 + 1 ≠ 0
h1 : ∀ (r : ℚ), r * (↑p + 1 + 1) * ↑n ^ succ p / (↑p + 1 + 1) = r * ↑n ^ succ p
h2 : f 1 + ↑n ^ succ p = 1 / 2 * ↑n ^ succ p
this :
  ∑ i in range p, bernoulli (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2) =
    ∑ i in range p, bernoulli' (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2)
⊢ ∑ i in range (succ (succ p)), f i + ↑n ^ succ p = ∑ i in range p, f (succ (succ i)) + f 1 + f 0 + ↑n ^ succ p

Next tactic:
simp_rw [sum_range_succ']
/-- Alternate form of **Faulhaber's theorem**, relating the sum of p-th powers to the Bernoulli
numbers: $$\sum_{k=1}^{n} k^p = \sum_{i=0}^p (-1)^iB_i\binom{p+1}{i}\frac{n^{p+1-i}}{p+1}.$$
Deduced from `sum_range_pow`. -/
theorem sum_Ico_pow (n p : ℕ) :
    (∑ k in Ico 1 (n + 1), (k : ℚ) ^ p) =
      ∑ i in range (p + 1), bernoulli' i * (p + 1).choose i * (n : ℚ) ^ (p + 1 - i) / (p + 1) := by
  rw [← Nat.cast_succ]
  -- dispose of the trivial case
  cases' p with p p
  · simp
  let f i := bernoulli i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  let f' i := bernoulli' i * p.succ.succ.choose i * (n : ℚ) ^ (p.succ.succ - i) / p.succ.succ
  suffices (∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ i in range p.succ.succ, f' i by convert this
  -- prove some algebraic facts that will make things easier for us later on
  have hle := Nat.le_add_left 1 n
  have hne : (p + 1 + 1 : ℚ) ≠ 0 := by norm_cast; exact succ_ne_zero p.succ
  have h1 : ∀ r : ℚ, r * (p + 1 + 1) * (n : ℚ) ^ p.succ / (p + 1 + 1 : ℚ) = r * (n : ℚ) ^ p.succ :=
      fun r => by rw [mul_div_right_comm, mul_div_cancel _ hne]
  have h2 : f 1 + (n : ℚ) ^ p.succ = 1 / 2 * (n : ℚ) ^ p.succ := by
    simp_rw [bernoulli_one, choose_one_right, succ_sub_succ_eq_sub, cast_succ, tsub_zero, h1]
    ring
  have :
    (∑ i in range p, bernoulli (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2)) =
      ∑ i in range p, bernoulli' (i + 2) * (p + 2).choose (i + 2) * (n : ℚ) ^ (p - i) / ↑(p + 2) :=
    sum_congr rfl fun i _ => by rw [bernoulli_eq_bernoulli'_of_ne_one (succ_succ_ne_one i)]
  calc
    (-- replace sum over `Ico` with sum over `range` and simplify
        ∑ k in Ico 1 n.succ, (k : ℚ) ^ p.succ) = ∑ k in range n.succ, (k : ℚ) ^ p.succ :=
      by simp [sum_Ico_eq_sub _ hle, succ_ne_zero]
    -- extract the last term of the sum
        _ = (∑ k in range n, (k : ℚ) ^ p.succ) + (n : ℚ) ^ p.succ :=
      by rw [sum_range_succ]
    -- apply the key lemma, `sum_range_pow`
        _ = (∑ i in range p.succ.succ, f i) + (n : ℚ) ^ p.succ :=
      by simp [sum_range_pow]
    -- extract the first two terms of the sum
        _ = (∑ i in range p, f i.succ.succ) + f 1 + f 0 + (n : ℚ) ^ p.succ :=
      by simp_rw [sum_range_succ']
        _ = (∑ i in range p, f i.succ.succ) + (f 1 + (n : ℚ) ^ p.succ) + f 0 := by 

Proof state:
A : Type u_1
inst✝¹ : CommRing A
inst✝ : Algebra ℚ A
n p : ℕ
f : ℕ → ℚ := fun i => bernoulli i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
f' : ℕ → ℚ := fun i => bernoulli' i * ↑(Nat.choose (succ (succ p)) i) * ↑n ^ (succ (succ p) - i) / ↑(succ (succ p))
hle : 1 ≤ n + 1
hne : ↑p + 1 + 1 ≠ 0
h1 : ∀ (r : ℚ), r * (↑p + 1 + 1) * ↑n ^ succ p / (↑p + 1 + 1) = r * ↑n ^ succ p
h2 : f 1 + ↑n ^ succ p = 1 / 2 * ↑n ^ succ p
this :
  ∑ i in range p, bernoulli (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2) =
    ∑ i in range p, bernoulli' (i + 2) * ↑(Nat.choose (p + 2) (i + 2)) * ↑n ^ (p - i) / ↑(p + 2)
⊢ ∑ i in range p, f (succ (succ i)) + f 1 + f 0 + ↑n ^ succ p =
    ∑ i in range p, f (succ (succ i)) + (f 1 + ↑n ^ succ p) + f 0

Next tactic:
ring
/-- To every `Monad C` we associated a monoid object in `C ⥤ C`.-/
@[simps]
def toMon (M : Monad C) : Mon_ (C ⥤ C) where
  X := (M : C ⥤ C)
  one := M.η
  mul := M.μ
  mul_assoc := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Monad C
⊢ MonoidalCategory.tensorHom (μ M) (𝟙 M.toFunctor) ≫ μ M =
    (MonoidalCategory.associator M.toFunctor M.toFunctor M.toFunctor).hom ≫
      MonoidalCategory.tensorHom (𝟙 M.toFunctor) (μ M) ≫ μ M

Next tactic:
ext
/-- To every `Monad C` we associated a monoid object in `C ⥤ C`.-/
@[simps]
def toMon (M : Monad C) : Mon_ (C ⥤ C) where
  X := (M : C ⥤ C)
  one := M.η
  mul := M.μ
  mul_assoc := by ext; 

Proof state:
case w.h
C : Type u
inst✝ : Category.{v, u} C
M : Monad C
x✝ : C
⊢ (MonoidalCategory.tensorHom (μ M) (𝟙 M.toFunctor) ≫ μ M).app x✝ =
    ((MonoidalCategory.associator M.toFunctor M.toFunctor M.toFunctor).hom ≫
          MonoidalCategory.tensorHom (𝟙 M.toFunctor) (μ M) ≫ μ M).app
      x✝

Next tactic:
simp [M.assoc]
/-- To every monoid object in `C ⥤ C` we associate a `Monad C`. -/
@[simps η μ]
def ofMon (M : Mon_ (C ⥤ C)) : Monad C where
  toFunctor := M.X
  η' := M.one
  μ' := M.mul
  left_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.id_hcomp_app M.one, ← NatTrans.comp_app, M.mul_one]
    rfl
  right_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.hcomp_id_app M.one, ← NatTrans.comp_app, M.one_mul]
    rfl
  assoc' := fun X => by
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Mon_ (C ⥤ C)
X : C
⊢ M.X.map (M.mul.app X) ≫ M.mul.app X = M.mul.app (M.X.obj X) ≫ M.mul.app X

Next tactic:
rw [← NatTrans.hcomp_id_app, ← NatTrans.comp_app]
/-- To every monoid object in `C ⥤ C` we associate a `Monad C`. -/
@[simps η μ]
def ofMon (M : Mon_ (C ⥤ C)) : Monad C where
  toFunctor := M.X
  η' := M.one
  μ' := M.mul
  left_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.id_hcomp_app M.one, ← NatTrans.comp_app, M.mul_one]
    rfl
  right_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.hcomp_id_app M.one, ← NatTrans.comp_app, M.one_mul]
    rfl
  assoc' := fun X => by
    rw [← NatTrans.hcomp_id_app, ← NatTrans.comp_app]
    -- Porting note: had to add this step:
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Mon_ (C ⥤ C)
X : C
⊢ ((M.mul ◫ 𝟙 M.X) ≫ M.mul).app X = M.mul.app (M.X.obj X) ≫ M.mul.app X

Next tactic:
erw [M.mul_assoc]
/-- To every monoid object in `C ⥤ C` we associate a `Monad C`. -/
@[simps η μ]
def ofMon (M : Mon_ (C ⥤ C)) : Monad C where
  toFunctor := M.X
  η' := M.one
  μ' := M.mul
  left_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.id_hcomp_app M.one, ← NatTrans.comp_app, M.mul_one]
    rfl
  right_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.hcomp_id_app M.one, ← NatTrans.comp_app, M.one_mul]
    rfl
  assoc' := fun X => by
    rw [← NatTrans.hcomp_id_app, ← NatTrans.comp_app]
    -- Porting note: had to add this step:
    erw [M.mul_assoc]
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Mon_ (C ⥤ C)
X : C
⊢ ((MonoidalCategory.associator M.X M.X M.X).hom ≫ MonoidalCategory.tensorHom (𝟙 M.X) M.mul ≫ M.mul).app X =
    M.mul.app (M.X.obj X) ≫ M.mul.app X

Next tactic:
simp
/-- To every monoid object in `C ⥤ C` we associate a `Monad C`. -/
@[simps η μ]
def ofMon (M : Mon_ (C ⥤ C)) : Monad C where
  toFunctor := M.X
  η' := M.one
  μ' := M.mul
  left_unit' := fun X => by
    -- Porting note: now using `erw`
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Mon_ (C ⥤ C)
X : C
⊢ M.one.app (M.X.obj X) ≫ M.mul.app X = 𝟙 ((𝟭 C).obj (M.X.obj X))

Next tactic:
erw [← NatTrans.id_hcomp_app M.one, ← NatTrans.comp_app, M.mul_one]
/-- To every monoid object in `C ⥤ C` we associate a `Monad C`. -/
@[simps η μ]
def ofMon (M : Mon_ (C ⥤ C)) : Monad C where
  toFunctor := M.X
  η' := M.one
  μ' := M.mul
  left_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.id_hcomp_app M.one, ← NatTrans.comp_app, M.mul_one]
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Mon_ (C ⥤ C)
X : C
⊢ (MonoidalCategory.rightUnitor M.X).hom.app X = 𝟙 ((𝟭 C).obj (M.X.obj X))

Next tactic:
rfl
/-- To every monoid object in `C ⥤ C` we associate a `Monad C`. -/
@[simps η μ]
def ofMon (M : Mon_ (C ⥤ C)) : Monad C where
  toFunctor := M.X
  η' := M.one
  μ' := M.mul
  left_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.id_hcomp_app M.one, ← NatTrans.comp_app, M.mul_one]
    rfl
  right_unit' := fun X => by
    -- Porting note: now using `erw`
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Mon_ (C ⥤ C)
X : C
⊢ M.X.map (M.one.app X) ≫ M.mul.app X = 𝟙 (M.X.obj ((𝟭 C).obj X))

Next tactic:
erw [← NatTrans.hcomp_id_app M.one, ← NatTrans.comp_app, M.one_mul]
/-- To every monoid object in `C ⥤ C` we associate a `Monad C`. -/
@[simps η μ]
def ofMon (M : Mon_ (C ⥤ C)) : Monad C where
  toFunctor := M.X
  η' := M.one
  μ' := M.mul
  left_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.id_hcomp_app M.one, ← NatTrans.comp_app, M.mul_one]
    rfl
  right_unit' := fun X => by
    -- Porting note: now using `erw`
    erw [← NatTrans.hcomp_id_app M.one, ← NatTrans.comp_app, M.one_mul]
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
M : Mon_ (C ⥤ C)
X : C
⊢ (MonoidalCategory.leftUnitor M.X).hom.app X = 𝟙 (M.X.obj ((𝟭 C).obj X))

Next tactic:
rfl
/-- Passing from `Mon_ (C ⥤ C)` to `Monad C` is functorial. -/
@[simps]
def monToMonad : Mon_ (C ⥤ C) ⥤ Monad C where
  obj := ofMon
  map {X Y} f :=
    { f.hom with
      app_η := by
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : Mon_ (C ⥤ C)
f : X ⟶ Y
src✝ : X.X ⟶ Y.X := f.hom
⊢ ∀ (X_1 : C), (η (ofMon X)).app X_1 ≫ (NatTrans.mk src✝.app).app X_1 = (η (ofMon Y)).app X_1

Next tactic:
intro X
/-- Passing from `Mon_ (C ⥤ C)` to `Monad C` is functorial. -/
@[simps]
def monToMonad : Mon_ (C ⥤ C) ⥤ Monad C where
  obj := ofMon
  map {X Y} f :=
    { f.hom with
      app_η := by
        intro X
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y : Mon_ (C ⥤ C)
f : X✝ ⟶ Y
src✝ : X✝.X ⟶ Y.X := f.hom
X : C
⊢ (η (ofMon X✝)).app X ≫ (NatTrans.mk src✝.app).app X = (η (ofMon Y)).app X

Next tactic:
erw [← NatTrans.comp_app, f.one_hom]
/-- Passing from `Mon_ (C ⥤ C)` to `Monad C` is functorial. -/
@[simps]
def monToMonad : Mon_ (C ⥤ C) ⥤ Monad C where
  obj := ofMon
  map {X Y} f :=
    { f.hom with
      app_η := by
        intro X
        erw [← NatTrans.comp_app, f.one_hom]
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y : Mon_ (C ⥤ C)
f : X✝ ⟶ Y
src✝ : X✝.X ⟶ Y.X := f.hom
X : C
⊢ Y.one.app X = (η (ofMon Y)).app X

Next tactic:
rfl
/-- Passing from `Mon_ (C ⥤ C)` to `Monad C` is functorial. -/
@[simps]
def monToMonad : Mon_ (C ⥤ C) ⥤ Monad C where
  obj := ofMon
  map {X Y} f :=
    { f.hom with
      app_η := by
        intro X
        erw [← NatTrans.comp_app, f.one_hom]
        rfl
      app_μ := by
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : Mon_ (C ⥤ C)
f : X ⟶ Y
src✝ : X.X ⟶ Y.X := f.hom
⊢ ∀ (X_1 : C),
    (μ (ofMon X)).app X_1 ≫ (NatTrans.mk src✝.app).app X_1 =
      ((ofMon X).toFunctor.map ((NatTrans.mk src✝.app).app X_1) ≫
          (NatTrans.mk src✝.app).app ((ofMon Y).toFunctor.obj X_1)) ≫
        (μ (ofMon Y)).app X_1

Next tactic:
intro Z
/-- Passing from `Mon_ (C ⥤ C)` to `Monad C` is functorial. -/
@[simps]
def monToMonad : Mon_ (C ⥤ C) ⥤ Monad C where
  obj := ofMon
  map {X Y} f :=
    { f.hom with
      app_η := by
        intro X
        erw [← NatTrans.comp_app, f.one_hom]
        rfl
      app_μ := by
        intro Z
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : Mon_ (C ⥤ C)
f : X ⟶ Y
src✝ : X.X ⟶ Y.X := f.hom
Z : C
⊢ (μ (ofMon X)).app Z ≫ (NatTrans.mk src✝.app).app Z =
    ((ofMon X).toFunctor.map ((NatTrans.mk src✝.app).app Z) ≫ (NatTrans.mk src✝.app).app ((ofMon Y).toFunctor.obj Z)) ≫
      (μ (ofMon Y)).app Z

Next tactic:
erw [← NatTrans.comp_app, f.mul_hom]
/-- Passing from `Mon_ (C ⥤ C)` to `Monad C` is functorial. -/
@[simps]
def monToMonad : Mon_ (C ⥤ C) ⥤ Monad C where
  obj := ofMon
  map {X Y} f :=
    { f.hom with
      app_η := by
        intro X
        erw [← NatTrans.comp_app, f.one_hom]
        rfl
      app_μ := by
        intro Z
        erw [← NatTrans.comp_app, f.mul_hom]
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : Mon_ (C ⥤ C)
f : X ⟶ Y
src✝ : X.X ⟶ Y.X := f.hom
Z : C
⊢ (MonoidalCategory.tensorHom f.hom f.hom ≫ Y.mul).app Z =
    ((ofMon X).toFunctor.map ((NatTrans.mk src✝.app).app Z) ≫ (NatTrans.mk src✝.app).app ((ofMon Y).toFunctor.obj Z)) ≫
      (μ (ofMon Y)).app Z

Next tactic:
dsimp
/-- Passing from `Mon_ (C ⥤ C)` to `Monad C` is functorial. -/
@[simps]
def monToMonad : Mon_ (C ⥤ C) ⥤ Monad C where
  obj := ofMon
  map {X Y} f :=
    { f.hom with
      app_η := by
        intro X
        erw [← NatTrans.comp_app, f.one_hom]
        rfl
      app_μ := by
        intro Z
        erw [← NatTrans.comp_app, f.mul_hom]
        dsimp
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : Mon_ (C ⥤ C)
f : X ⟶ Y
src✝ : X.X ⟶ Y.X := f.hom
Z : C
⊢ (f.hom.app (X.X.obj Z) ≫ Y.X.map (f.hom.app Z)) ≫ Y.mul.app Z =
    ((ofMon X).toFunctor.map (f.hom.app Z) ≫ f.hom.app (Y.X.obj Z)) ≫ Y.mul.app Z

Next tactic:
simp only [NatTrans.naturality, NatTrans.hcomp_app, assoc, NatTrans.comp_app,
          ofMon_μ]
@[simp]
theorem iterate_id (n : ℕ) : (id : α → α)^[n] = id :=
  Nat.recOn n rfl fun n ihn ↦ by 

Proof state:
α : Type u
β : Type v
f : α → α
n✝ n : ℕ
ihn : id^[n] = id
⊢ id^[Nat.succ n] = id

Next tactic:
rw [iterate_succ, ihn, comp.left_id]
theorem iterate_add (m : ℕ) : ∀ n : ℕ, f^[m + n] = f^[m] ∘ f^[n]
  | 0 => rfl
  | Nat.succ n => by 

Proof state:
α : Type u
β : Type v
f : α → α
m n : ℕ
⊢ f^[m + Nat.succ n] = f^[m] ∘ f^[Nat.succ n]

Next tactic:
rw [Nat.add_succ, iterate_succ, iterate_succ, iterate_add m n]
theorem iterate_add (m : ℕ) : ∀ n : ℕ, f^[m + n] = f^[m] ∘ f^[n]
  | 0 => rfl
  | Nat.succ n => by rw [Nat.add_succ, iterate_succ, iterate_succ, iterate_add m n]; 

Proof state:
α : Type u
β : Type v
f : α → α
m n : ℕ
⊢ (f^[m] ∘ f^[n]) ∘ f = f^[m] ∘ f^[n] ∘ f

Next tactic:
rfl
theorem iterate_add_apply (m n : ℕ) (x : α) : f^[m + n] x = f^[m] (f^[n] x) := by
  

Proof state:
α : Type u
β : Type v
f : α → α
m n : ℕ
x : α
⊢ f^[m + n] x = f^[m] (f^[n] x)

Next tactic:
rw [iterate_add f m n]
theorem iterate_add_apply (m n : ℕ) (x : α) : f^[m + n] x = f^[m] (f^[n] x) := by
  rw [iterate_add f m n]
  

Proof state:
α : Type u
β : Type v
f : α → α
m n : ℕ
x : α
⊢ (f^[m] ∘ f^[n]) x = f^[m] (f^[n] x)

Next tactic:
rfl
theorem iterate_mul (m : ℕ) : ∀ n, f^[m * n] = f^[m]^[n]
  | 0 => by 

Proof state:
α : Type u
β : Type v
f : α → α
m : ℕ
⊢ f^[m * 0] = f^[m]^[0]

Next tactic:
simp only [Nat.mul_zero, iterate_zero]
theorem iterate_mul (m : ℕ) : ∀ n, f^[m * n] = f^[m]^[n]
  | 0 => by simp only [Nat.mul_zero, iterate_zero]
  | n + 1 => by 

Proof state:
α : Type u
β : Type v
f : α → α
m n : ℕ
⊢ f^[m * (n + 1)] = f^[m]^[n + 1]

Next tactic:
simp only [Nat.mul_succ, Nat.mul_one, iterate_one, iterate_add, iterate_mul m n]
theorem iterate_fixed {x} (h : f x = x) (n : ℕ) : f^[n] x = x :=
  Nat.recOn n rfl fun n ihn ↦ by 

Proof state:
α : Type u
β : Type v
f : α → α
x : α
h : f x = x
n✝ n : ℕ
ihn : f^[n] x = x
⊢ f^[Nat.succ n] x = x

Next tactic:
rw [iterate_succ_apply, h, ihn]
theorem iterate_left {g : ℕ → α → α} (H : ∀ n, Semiconj f (g n) (g <| n + 1)) (n k : ℕ) :
    Semiconj f^[n] (g k) (g <| n + k) := by
  

Proof state:
α : Type u
β : Type v
f : α → α
g : ℕ → α → α
H : ∀ (n : ℕ), Semiconj f (g n) (g (n + 1))
n k : ℕ
⊢ Semiconj f^[n] (g k) (g (n + k))

Next tactic:
induction n generalizing k with
  | zero =>
    rw [Nat.zero_add]
    exact id_left
  | succ n ihn =>
    rw [Nat.succ_eq_add_one, Nat.add_right_comm, Nat.add_assoc]
    exact (H k).comp_left (ihn (k + 1))
theorem iterate_left {g : ℕ → α → α} (H : ∀ n, Semiconj f (g n) (g <| n + 1)) (n k : ℕ) :
    Semiconj f^[n] (g k) (g <| n + k) := by
  induction n generalizing k with
  

Proof state:
case zero
α : Type u
β : Type v
f : α → α
g : ℕ → α → α
H : ∀ (n : ℕ), Semiconj f (g n) (g (n + 1))
k : ℕ
⊢ Semiconj f^[Nat.zero] (g k) (g (Nat.zero + k))

Next tactic:
| zero =>
    rw [Nat.zero_add]
    exact id_left