l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem Antitone.mulIndicator_eventuallyEq_iInter {ι} [Preorder ι] [One β] (s : ι → Set α)
    (hs : Antitone s) (f : α → β) (a : α) :
    (fun i => mulIndicator (s i) f a) =ᶠ[atTop] fun _ ↦ mulIndicator (⋂ i, s i) f a := by
  

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
ι : Type u_5
inst✝¹ : Preorder ι
inst✝ : One β
s : ι → Set α
hs : Antitone s
f : α → β
a : α
⊢ (fun i => mulIndicator (s i) f a) =ᶠ[atTop] fun x => mulIndicator (⋂ i, s i) f a

Next tactic:
classical exact hs.piecewise_eventually_eq_iInter f 1 a
@[to_additive]
theorem Antitone.mulIndicator_eventuallyEq_iInter {ι} [Preorder ι] [One β] (s : ι → Set α)
    (hs : Antitone s) (f : α → β) (a : α) :
    (fun i => mulIndicator (s i) f a) =ᶠ[atTop] fun _ ↦ mulIndicator (⋂ i, s i) f a := by
  classical 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
ι : Type u_5
inst✝¹ : Preorder ι
inst✝ : One β
s : ι → Set α
hs : Antitone s
f : α → β
a : α
⊢ (fun i => mulIndicator (s i) f a) =ᶠ[atTop] fun x => mulIndicator (⋂ i, s i) f a

Next tactic:
exact hs.piecewise_eventually_eq_iInter f 1 a
@[to_additive]
theorem mulIndicator_biUnion_finset_eventuallyEq {ι} [One β] (s : ι → Set α) (f : α → β) (a : α) :
    (fun n : Finset ι => mulIndicator (⋃ i ∈ n, s i) f a) =ᶠ[atTop]
      fun _ ↦ mulIndicator (iUnion s) f a := by
  

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
ι : Type u_5
inst✝ : One β
s : ι → Set α
f : α → β
a : α
⊢ (fun n => mulIndicator (⋃ i ∈ n, s i) f a) =ᶠ[atTop] fun x => mulIndicator (iUnion s) f a

Next tactic:
rw [iUnion_eq_iUnion_finset s]
@[to_additive]
theorem mulIndicator_biUnion_finset_eventuallyEq {ι} [One β] (s : ι → Set α) (f : α → β) (a : α) :
    (fun n : Finset ι => mulIndicator (⋃ i ∈ n, s i) f a) =ᶠ[atTop]
      fun _ ↦ mulIndicator (iUnion s) f a := by
  rw [iUnion_eq_iUnion_finset s]
  

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
ι : Type u_5
inst✝ : One β
s : ι → Set α
f : α → β
a : α
⊢ (fun n => mulIndicator (⋃ i ∈ n, s i) f a) =ᶠ[atTop] fun x => mulIndicator (⋃ t, ⋃ i ∈ t, s i) f a

Next tactic:
apply Monotone.mulIndicator_eventuallyEq_iUnion
@[to_additive]
theorem mulIndicator_biUnion_finset_eventuallyEq {ι} [One β] (s : ι → Set α) (f : α → β) (a : α) :
    (fun n : Finset ι => mulIndicator (⋃ i ∈ n, s i) f a) =ᶠ[atTop]
      fun _ ↦ mulIndicator (iUnion s) f a := by
  rw [iUnion_eq_iUnion_finset s]
  apply Monotone.mulIndicator_eventuallyEq_iUnion
  

Proof state:
case hs
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
ι : Type u_5
inst✝ : One β
s : ι → Set α
f : α → β
a : α
⊢ Monotone fun i => ⋃ i_1 ∈ i, s i_1

Next tactic:
exact fun _ _ ↦ biUnion_subset_biUnion_left
@[to_additive]
theorem Filter.EventuallyEq.mulIndicator_one [One β] {l : Filter α} {f : α → β} {s : Set α}
    (hf : f =ᶠ[l] 1) : s.mulIndicator f =ᶠ[l] 1 :=
  hf.mulIndicator.trans <| by 

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
inst✝ : One β
l : Filter α
f : α → β
s : Set α
hf : f =ᶠ[l] 1
⊢ mulIndicator s 1 =ᶠ[l] 1

Next tactic:
rw [mulIndicator_one']
@[to_additive]
theorem Filter.EventuallyEq.of_mulIndicator [One β] {l : Filter α} {f : α → β}
    (hf : ∀ᶠ x in l, f x ≠ 1) {s t : Set α} (h : s.mulIndicator f =ᶠ[l] t.mulIndicator f) :
    s =ᶠ[l] t := by
  

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
inst✝ : One β
l : Filter α
f : α → β
hf : ∀ᶠ (x : α) in l, f x ≠ 1
s t : Set α
h : mulIndicator s f =ᶠ[l] mulIndicator t f
⊢ s =ᶠ[l] t

Next tactic:
have : ∀ {s : Set α}, Function.mulSupport (s.mulIndicator f) =ᶠ[l] s := fun {s} ↦ by
    rw [mulSupport_mulIndicator]
    exact (hf.mono fun x hx ↦ and_iff_left hx).set_eq
@[to_additive]
theorem Filter.EventuallyEq.of_mulIndicator [One β] {l : Filter α} {f : α → β}
    (hf : ∀ᶠ x in l, f x ≠ 1) {s t : Set α} (h : s.mulIndicator f =ᶠ[l] t.mulIndicator f) :
    s =ᶠ[l] t := by
  have : ∀ {s : Set α}, Function.mulSupport (s.mulIndicator f) =ᶠ[l] s := fun {s} ↦ by
    

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
inst✝ : One β
l : Filter α
f : α → β
hf : ∀ᶠ (x : α) in l, f x ≠ 1
s✝ t : Set α
h : mulIndicator s✝ f =ᶠ[l] mulIndicator t f
s : Set α
⊢ Function.mulSupport (mulIndicator s f) =ᶠ[l] s

Next tactic:
rw [mulSupport_mulIndicator]
@[to_additive]
theorem Filter.EventuallyEq.of_mulIndicator [One β] {l : Filter α} {f : α → β}
    (hf : ∀ᶠ x in l, f x ≠ 1) {s t : Set α} (h : s.mulIndicator f =ᶠ[l] t.mulIndicator f) :
    s =ᶠ[l] t := by
  have : ∀ {s : Set α}, Function.mulSupport (s.mulIndicator f) =ᶠ[l] s := fun {s} ↦ by
    rw [mulSupport_mulIndicator]
    

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
inst✝ : One β
l : Filter α
f : α → β
hf : ∀ᶠ (x : α) in l, f x ≠ 1
s✝ t : Set α
h : mulIndicator s✝ f =ᶠ[l] mulIndicator t f
s : Set α
⊢ s ∩ Function.mulSupport f =ᶠ[l] s

Next tactic:
exact (hf.mono fun x hx ↦ and_iff_left hx).set_eq
@[to_additive]
theorem Filter.EventuallyEq.of_mulIndicator [One β] {l : Filter α} {f : α → β}
    (hf : ∀ᶠ x in l, f x ≠ 1) {s t : Set α} (h : s.mulIndicator f =ᶠ[l] t.mulIndicator f) :
    s =ᶠ[l] t := by
  have : ∀ {s : Set α}, Function.mulSupport (s.mulIndicator f) =ᶠ[l] s := fun {s} ↦ by
    rw [mulSupport_mulIndicator]
    exact (hf.mono fun x hx ↦ and_iff_left hx).set_eq
  

Proof state:
α : Type u_1
β : Type u_2
M : Type u_3
E : Type u_4
inst✝ : One β
l : Filter α
f : α → β
hf : ∀ᶠ (x : α) in l, f x ≠ 1
s t : Set α
h : mulIndicator s f =ᶠ[l] mulIndicator t f
this : ∀ {s : Set α}, Function.mulSupport (mulIndicator s f) =ᶠ[l] s
⊢ s =ᶠ[l] t

Next tactic:
exact this.symm.trans <| h.mulSupport.trans this
instance : Monoid (Monoid.CoprodI M) :=
  by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
⊢ Monoid (Monoid.CoprodI M)

Next tactic:
delta Monoid.CoprodI
instance : Monoid (Monoid.CoprodI M) :=
  by delta Monoid.CoprodI; 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
⊢ Monoid (Con.Quotient (conGen (Monoid.CoprodI.Rel M)))

Next tactic:
infer_instance
/-- See note [partially-applied ext lemmas]. -/
--Porting note: higher `ext` priority
@[ext 1100]
theorem ext_hom (f g : CoprodI M →* N) (h : ∀ i, f.comp (of : M i →* _) = g.comp of) : f = g :=
  (MonoidHom.cancel_right Con.mk'_surjective).mp <|
    FreeMonoid.hom_eq fun ⟨i, x⟩ => by
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
f g : CoprodI M →* N
h : ∀ (i : ι), MonoidHom.comp f of = MonoidHom.comp g of
x✝ : (i : ι) × M i
i : ι
x : M i
⊢ (MonoidHom.comp f (Con.mk' (conGen (Rel M)))) (FreeMonoid.of { fst := i, snd := x }) =
    (MonoidHom.comp g (Con.mk' (conGen (Rel M)))) (FreeMonoid.of { fst := i, snd := x })

Next tactic:
erw [MonoidHom.comp_apply, MonoidHom.comp_apply, ← of_apply, ← MonoidHom.comp_apply, ←
        MonoidHom.comp_apply, h]
/-- See note [partially-applied ext lemmas]. -/
--Porting note: higher `ext` priority
@[ext 1100]
theorem ext_hom (f g : CoprodI M →* N) (h : ∀ i, f.comp (of : M i →* _) = g.comp of) : f = g :=
  (MonoidHom.cancel_right Con.mk'_surjective).mp <|
    FreeMonoid.hom_eq fun ⟨i, x⟩ => by
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      erw [MonoidHom.comp_apply, MonoidHom.comp_apply, ← of_apply, ← MonoidHom.comp_apply, ←
        MonoidHom.comp_apply, h]; 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
f g : CoprodI M →* N
h : ∀ (i : ι), MonoidHom.comp f of = MonoidHom.comp g of
x✝ : (i : ι) × M i
i : ι
x : M i
⊢ (MonoidHom.comp g of) x = (MonoidHom.comp g (Con.mk' (conGen (Rel M)))) (FreeMonoid.of { fst := i, snd := x })

Next tactic:
rfl
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
⊢ ∀ (x y : FreeMonoid ((i : ι) × M i)), Rel M x y → (Con.ker (FreeMonoid.lift fun p => (fi p.fst) p.snd)) x y

Next tactic:
simp_rw [Con.ker_rel]
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
⊢ ∀ (x y : FreeMonoid ((i : ι) × M i)),
    Rel M x y → (FreeMonoid.lift fun p => (fi p.fst) p.snd) x = (FreeMonoid.lift fun p => (fi p.fst) p.snd) y

Next tactic:
rintro _ _ (i | ⟨x, y⟩)
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · 

Proof state:
case of_one
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
i : ι
⊢ (FreeMonoid.lift fun p => (fi p.fst) p.snd) (FreeMonoid.of { fst := i, snd := 1 }) =
    (FreeMonoid.lift fun p => (fi p.fst) p.snd) 1

Next tactic:
change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          

Proof state:
case of_one
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
i : ι
⊢ (FreeMonoid.lift fun p => (fi p.fst) p.snd) (FreeMonoid.of { fst := i, snd := 1 }) =
    (FreeMonoid.lift fun p => (fi p.fst) p.snd) 1

Next tactic:
simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · 

Proof state:
case of_mul
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
i✝ : ι
x y : M i✝
⊢ (FreeMonoid.lift fun p => (fi p.fst) p.snd)
      (FreeMonoid.of { fst := i✝, snd := x } * FreeMonoid.of { fst := i✝, snd := y }) =
    (FreeMonoid.lift fun p => (fi p.fst) p.snd) (FreeMonoid.of { fst := i✝, snd := x * y })

Next tactic:
change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
          

Proof state:
case of_mul
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
i✝ : ι
x y : M i✝
⊢ (FreeMonoid.lift fun p => (fi p.fst) p.snd)
      (FreeMonoid.of { fst := i✝, snd := x } * FreeMonoid.of { fst := i✝, snd := y }) =
    (FreeMonoid.lift fun p => (fi p.fst) p.snd) (FreeMonoid.of { fst := i✝, snd := x * y })

Next tactic:
simp only [MonoidHom.map_mul, FreeMonoid.lift_eval_of]
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
          simp only [MonoidHom.map_mul, FreeMonoid.lift_eval_of]
  invFun f i := f.comp of
  left_inv := by
    

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
⊢ Function.LeftInverse (fun f i => MonoidHom.comp f of) fun fi =>
    Con.lift (conGen (Rel M)) (FreeMonoid.lift fun p => (fi p.fst) p.snd)
      (_ : conGen (Rel M) ≤ Con.ker (FreeMonoid.lift fun p => (fi p.fst) p.snd))

Next tactic:
intro fi
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
          simp only [MonoidHom.map_mul, FreeMonoid.lift_eval_of]
  invFun f i := f.comp of
  left_inv := by
    intro fi
    

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
⊢ (fun f i => MonoidHom.comp f of)
      ((fun fi =>
          Con.lift (conGen (Rel M)) (FreeMonoid.lift fun p => (fi p.fst) p.snd)
            (_ : conGen (Rel M) ≤ Con.ker (FreeMonoid.lift fun p => (fi p.fst) p.snd)))
        fi) =
    fi

Next tactic:
ext i x
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
          simp only [MonoidHom.map_mul, FreeMonoid.lift_eval_of]
  invFun f i := f.comp of
  left_inv := by
    intro fi
    ext i x
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    

Proof state:
case h.h
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
fi : (i : ι) → M i →* N
i : ι
x : M i
⊢ ((fun f i => MonoidHom.comp f of)
        ((fun fi =>
            Con.lift (conGen (Rel M)) (FreeMonoid.lift fun p => (fi p.fst) p.snd)
              (_ : conGen (Rel M) ≤ Con.ker (FreeMonoid.lift fun p => (fi p.fst) p.snd)))
          fi)
        i)
      x =
    (fi i) x

Next tactic:
erw [MonoidHom.comp_apply, of_apply, Con.lift_mk', FreeMonoid.lift_eval_of]
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
          simp only [MonoidHom.map_mul, FreeMonoid.lift_eval_of]
  invFun f i := f.comp of
  left_inv := by
    intro fi
    ext i x
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    erw [MonoidHom.comp_apply, of_apply, Con.lift_mk', FreeMonoid.lift_eval_of]
  right_inv := by
    

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
⊢ Function.RightInverse (fun f i => MonoidHom.comp f of) fun fi =>
    Con.lift (conGen (Rel M)) (FreeMonoid.lift fun p => (fi p.fst) p.snd)
      (_ : conGen (Rel M) ≤ Con.ker (FreeMonoid.lift fun p => (fi p.fst) p.snd))

Next tactic:
intro f
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
          simp only [MonoidHom.map_mul, FreeMonoid.lift_eval_of]
  invFun f i := f.comp of
  left_inv := by
    intro fi
    ext i x
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    erw [MonoidHom.comp_apply, of_apply, Con.lift_mk', FreeMonoid.lift_eval_of]
  right_inv := by
    intro f
    

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
f : CoprodI M →* N
⊢ (fun fi =>
        Con.lift (conGen (Rel M)) (FreeMonoid.lift fun p => (fi p.fst) p.snd)
          (_ : conGen (Rel M) ≤ Con.ker (FreeMonoid.lift fun p => (fi p.fst) p.snd)))
      ((fun f i => MonoidHom.comp f of) f) =
    f

Next tactic:
ext i x
/-- A map out of the free product corresponds to a family of maps out of the summands. This is the
universal property of the free product, characterizing it as a categorical coproduct. -/
@[simps symm_apply]
def lift : (∀ i, M i →* N) ≃ (CoprodI M →* N) where
  toFun fi :=
    Con.lift _ (FreeMonoid.lift fun p : Σi, M i => fi p.fst p.snd) <|
      Con.conGen_le <| by
        simp_rw [Con.ker_rel]
        rintro _ _ (i | ⟨x, y⟩)
        · change FreeMonoid.lift _ (FreeMonoid.of _) = FreeMonoid.lift _ 1
          simp only [MonoidHom.map_one, FreeMonoid.lift_eval_of]
        · change
            FreeMonoid.lift _ (FreeMonoid.of _ * FreeMonoid.of _) =
              FreeMonoid.lift _ (FreeMonoid.of _)
          simp only [MonoidHom.map_mul, FreeMonoid.lift_eval_of]
  invFun f i := f.comp of
  left_inv := by
    intro fi
    ext i x
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    erw [MonoidHom.comp_apply, of_apply, Con.lift_mk', FreeMonoid.lift_eval_of]
  right_inv := by
    intro f
    ext i x
    

Proof state:
case h.h
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
f : CoprodI M →* N
i : ι
x : M i
⊢ (MonoidHom.comp
        ((fun fi =>
            Con.lift (conGen (Rel M)) (FreeMonoid.lift fun p => (fi p.fst) p.snd)
              (_ : conGen (Rel M) ≤ Con.ker (FreeMonoid.lift fun p => (fi p.fst) p.snd)))
          ((fun f i => MonoidHom.comp f of) f))
        of)
      x =
    (MonoidHom.comp f of) x

Next tactic:
rfl
@[simp]
theorem lift_of {N} [Monoid N] (fi : ∀ i, M i →* N) {i} (m : M i) : lift fi (of m) = fi i m := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N✝ : Type u_3
inst✝¹ : Monoid N✝
N : Type u_4
inst✝ : Monoid N
fi : (i : ι) → M i →* N
i : ι
m : M i
⊢ (lift fi) (of m) = (fi i) m

Next tactic:
conv_rhs => rw [← lift.symm_apply_apply fi, lift_symm_apply, MonoidHom.comp_apply]
@[simp]
theorem lift_of {N} [Monoid N] (fi : ∀ i, M i →* N) {i} (m : M i) : lift fi (of m) = fi i m := by
  conv_rhs => 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N✝ : Type u_3
inst✝¹ : Monoid N✝
N : Type u_4
inst✝ : Monoid N
fi : (i : ι) → M i →* N
i : ι
m : M i
| (fi i) m

Next tactic:
rw [← lift.symm_apply_apply fi, lift_symm_apply, MonoidHom.comp_apply]
@[elab_as_elim]
theorem induction_on {C : CoprodI M → Prop} (m : CoprodI M) (h_one : C 1)
    (h_of : ∀ (i) (m : M i), C (of m)) (h_mul : ∀ x y, C x → C y → C (x * y)) : C m := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
C : CoprodI M → Prop
m : CoprodI M
h_one : C 1
h_of : ∀ (i : ι) (m : M i), C (of m)
h_mul : ∀ (x y : CoprodI M), C x → C y → C (x * y)
⊢ C m

Next tactic:
let S : Submonoid (CoprodI M) :=
    { carrier := setOf C
      mul_mem' := h_mul _ _
      one_mem' := h_one }
@[elab_as_elim]
theorem induction_on {C : CoprodI M → Prop} (m : CoprodI M) (h_one : C 1)
    (h_of : ∀ (i) (m : M i), C (of m)) (h_mul : ∀ x y, C x → C y → C (x * y)) : C m := by
  let S : Submonoid (CoprodI M) :=
    { carrier := setOf C
      mul_mem' := h_mul _ _
      one_mem' := h_one }
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
C : CoprodI M → Prop
m : CoprodI M
h_one : C 1
h_of : ∀ (i : ι) (m : M i), C (of m)
h_mul : ∀ (x y : CoprodI M), C x → C y → C (x * y)
S : Submonoid (CoprodI M) :=
  { toSubsemigroup := { carrier := setOf C, mul_mem' := (_ : ∀ {a b : CoprodI M}, C a → C b → C (a * b)) },
    one_mem' := h_one }
⊢ C m

Next tactic:
have : C _ := Subtype.prop (lift (fun i => of.codRestrict S (h_of i)) m)
@[elab_as_elim]
theorem induction_on {C : CoprodI M → Prop} (m : CoprodI M) (h_one : C 1)
    (h_of : ∀ (i) (m : M i), C (of m)) (h_mul : ∀ x y, C x → C y → C (x * y)) : C m := by
  let S : Submonoid (CoprodI M) :=
    { carrier := setOf C
      mul_mem' := h_mul _ _
      one_mem' := h_one }
  have : C _ := Subtype.prop (lift (fun i => of.codRestrict S (h_of i)) m)
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
C : CoprodI M → Prop
m : CoprodI M
h_one : C 1
h_of : ∀ (i : ι) (m : M i), C (of m)
h_mul : ∀ (x y : CoprodI M), C x → C y → C (x * y)
S : Submonoid (CoprodI M) :=
  { toSubsemigroup := { carrier := setOf C, mul_mem' := (_ : ∀ {a b : CoprodI M}, C a → C b → C (a * b)) },
    one_mem' := h_one }
this : C ↑((lift fun i => MonoidHom.codRestrict of S (_ : ∀ (m : M i), C (of m))) m)
⊢ C m

Next tactic:
convert this