l3lab/ntp-mathlib huggingface dataset:
/-- If `C` has (small) wide equalizers and a weakly initial object, then it has an initial object.

The initial object is constructed as the wide equalizer of all endomorphisms on the given weakly
initial object.
-/
theorem hasInitial_of_weakly_initial_and_hasWideEqualizers [HasWideEqualizers.{v} C] {T : C}
    (hT : ∀ X, Nonempty (T ⟶ X)) : HasInitial C := by
  let endos := T ⟶ T
  let i := wideEqualizer.ι (id : endos → endos)
  haveI : Nonempty endos := ⟨𝟙 _⟩
  have : ∀ X : C, Unique (wideEqualizer (id : endos → endos) ⟶ X) := by
    intro X
    refine' ⟨⟨i ≫ Classical.choice (hT X)⟩, fun a => _⟩
    let E := equalizer a (i ≫ Classical.choice (hT _))
    let e : E ⟶ wideEqualizer id := equalizer.ι _ _
    let h : T ⟶ E := Classical.choice (hT E)
    have : ((i ≫ h) ≫ e) ≫ i = i ≫ 𝟙 _ := by
      rw [Category.assoc, Category.assoc]
      apply wideEqualizer.condition (id : endos → endos) (h ≫ e ≫ i)
    rw [Category.comp_id, cancel_mono_id i] at this
    

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasWideEqualizers C
T : C
hT : ∀ (X : C), Nonempty (T ⟶ X)
endos : Type v := T ⟶ T
i : wideEqualizer id ⟶ T := wideEqualizer.ι id
this✝ : Nonempty endos
X : C
a : wideEqualizer id ⟶ X
E : C := equalizer a (i ≫ Classical.choice (_ : Nonempty (T ⟶ X)))
e : E ⟶ wideEqualizer id := equalizer.ι a (i ≫ Classical.choice (_ : Nonempty (T ⟶ X)))
h : T ⟶ E := Classical.choice (_ : Nonempty (T ⟶ E))
this : (i ≫ h) ≫ e = 𝟙 (wideEqualizer id)
⊢ a = default

Next tactic:
haveI : IsSplitEpi e := IsSplitEpi.mk' ⟨i ≫ h, this⟩
/-- If `C` has (small) wide equalizers and a weakly initial object, then it has an initial object.

The initial object is constructed as the wide equalizer of all endomorphisms on the given weakly
initial object.
-/
theorem hasInitial_of_weakly_initial_and_hasWideEqualizers [HasWideEqualizers.{v} C] {T : C}
    (hT : ∀ X, Nonempty (T ⟶ X)) : HasInitial C := by
  let endos := T ⟶ T
  let i := wideEqualizer.ι (id : endos → endos)
  haveI : Nonempty endos := ⟨𝟙 _⟩
  have : ∀ X : C, Unique (wideEqualizer (id : endos → endos) ⟶ X) := by
    intro X
    refine' ⟨⟨i ≫ Classical.choice (hT X)⟩, fun a => _⟩
    let E := equalizer a (i ≫ Classical.choice (hT _))
    let e : E ⟶ wideEqualizer id := equalizer.ι _ _
    let h : T ⟶ E := Classical.choice (hT E)
    have : ((i ≫ h) ≫ e) ≫ i = i ≫ 𝟙 _ := by
      rw [Category.assoc, Category.assoc]
      apply wideEqualizer.condition (id : endos → endos) (h ≫ e ≫ i)
    rw [Category.comp_id, cancel_mono_id i] at this
    haveI : IsSplitEpi e := IsSplitEpi.mk' ⟨i ≫ h, this⟩
    

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasWideEqualizers C
T : C
hT : ∀ (X : C), Nonempty (T ⟶ X)
endos : Type v := T ⟶ T
i : wideEqualizer id ⟶ T := wideEqualizer.ι id
this✝¹ : Nonempty endos
X : C
a : wideEqualizer id ⟶ X
E : C := equalizer a (i ≫ Classical.choice (_ : Nonempty (T ⟶ X)))
e : E ⟶ wideEqualizer id := equalizer.ι a (i ≫ Classical.choice (_ : Nonempty (T ⟶ X)))
h : T ⟶ E := Classical.choice (_ : Nonempty (T ⟶ E))
this✝ : (i ≫ h) ≫ e = 𝟙 (wideEqualizer id)
this : IsSplitEpi e
⊢ a = default

Next tactic:
rw [← cancel_epi e]
/-- If `C` has (small) wide equalizers and a weakly initial object, then it has an initial object.

The initial object is constructed as the wide equalizer of all endomorphisms on the given weakly
initial object.
-/
theorem hasInitial_of_weakly_initial_and_hasWideEqualizers [HasWideEqualizers.{v} C] {T : C}
    (hT : ∀ X, Nonempty (T ⟶ X)) : HasInitial C := by
  let endos := T ⟶ T
  let i := wideEqualizer.ι (id : endos → endos)
  haveI : Nonempty endos := ⟨𝟙 _⟩
  have : ∀ X : C, Unique (wideEqualizer (id : endos → endos) ⟶ X) := by
    intro X
    refine' ⟨⟨i ≫ Classical.choice (hT X)⟩, fun a => _⟩
    let E := equalizer a (i ≫ Classical.choice (hT _))
    let e : E ⟶ wideEqualizer id := equalizer.ι _ _
    let h : T ⟶ E := Classical.choice (hT E)
    have : ((i ≫ h) ≫ e) ≫ i = i ≫ 𝟙 _ := by
      rw [Category.assoc, Category.assoc]
      apply wideEqualizer.condition (id : endos → endos) (h ≫ e ≫ i)
    rw [Category.comp_id, cancel_mono_id i] at this
    haveI : IsSplitEpi e := IsSplitEpi.mk' ⟨i ≫ h, this⟩
    rw [← cancel_epi e]
    

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasWideEqualizers C
T : C
hT : ∀ (X : C), Nonempty (T ⟶ X)
endos : Type v := T ⟶ T
i : wideEqualizer id ⟶ T := wideEqualizer.ι id
this✝¹ : Nonempty endos
X : C
a : wideEqualizer id ⟶ X
E : C := equalizer a (i ≫ Classical.choice (_ : Nonempty (T ⟶ X)))
e : E ⟶ wideEqualizer id := equalizer.ι a (i ≫ Classical.choice (_ : Nonempty (T ⟶ X)))
h : T ⟶ E := Classical.choice (_ : Nonempty (T ⟶ E))
this✝ : (i ≫ h) ≫ e = 𝟙 (wideEqualizer id)
this : IsSplitEpi e
⊢ e ≫ a = e ≫ default

Next tactic:
apply equalizer.condition
/-- If `C` has (small) wide equalizers and a weakly initial object, then it has an initial object.

The initial object is constructed as the wide equalizer of all endomorphisms on the given weakly
initial object.
-/
theorem hasInitial_of_weakly_initial_and_hasWideEqualizers [HasWideEqualizers.{v} C] {T : C}
    (hT : ∀ X, Nonempty (T ⟶ X)) : HasInitial C := by
  let endos := T ⟶ T
  let i := wideEqualizer.ι (id : endos → endos)
  haveI : Nonempty endos := ⟨𝟙 _⟩
  have : ∀ X : C, Unique (wideEqualizer (id : endos → endos) ⟶ X) := by
    intro X
    refine' ⟨⟨i ≫ Classical.choice (hT X)⟩, fun a => _⟩
    let E := equalizer a (i ≫ Classical.choice (hT _))
    let e : E ⟶ wideEqualizer id := equalizer.ι _ _
    let h : T ⟶ E := Classical.choice (hT E)
    have : ((i ≫ h) ≫ e) ≫ i = i ≫ 𝟙 _ := by
      rw [Category.assoc, Category.assoc]
      apply wideEqualizer.condition (id : endos → endos) (h ≫ e ≫ i)
    rw [Category.comp_id, cancel_mono_id i] at this
    haveI : IsSplitEpi e := IsSplitEpi.mk' ⟨i ≫ h, this⟩
    rw [← cancel_epi e]
    apply equalizer.condition
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasWideEqualizers C
T : C
hT : ∀ (X : C), Nonempty (T ⟶ X)
endos : Type v := T ⟶ T
i : wideEqualizer id ⟶ T := wideEqualizer.ι id
this✝ : Nonempty endos
this : (X : C) → Unique (wideEqualizer id ⟶ X)
⊢ HasInitial C

Next tactic:
exact hasInitial_of_unique (wideEqualizer (id : endos → endos))
theorem top_mul_top : (⊤ * ⊤ : WithTop α) = ⊤ := by 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
⊢ ⊤ * ⊤ = ⊤

Next tactic:
simp [mul_def]
theorem top_mul_top : (⊤ * ⊤ : WithTop α) = ⊤ := by simp [mul_def]; 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
⊢ Option.map₂ (fun x x_1 => x * x_1) ⊤ ⊤ = ⊤

Next tactic:
rfl
theorem mul_top' (a : WithTop α) : a * ⊤ = if a = 0 then 0 else ⊤ := by
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a : WithTop α
⊢ a * ⊤ = if a = 0 then 0 else ⊤

Next tactic:
induction a using recTopCoe
theorem mul_top' (a : WithTop α) : a * ⊤ = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> 

Proof state:
case top
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
⊢ ⊤ * ⊤ = if ⊤ = 0 then 0 else ⊤

Next tactic:
simp [mul_def]
theorem mul_top' (a : WithTop α) : a * ⊤ = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> 

Proof state:
case coe
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a✝ : α
⊢ ↑a✝ * ⊤ = if ↑a✝ = 0 then 0 else ⊤

Next tactic:
simp [mul_def]
theorem mul_top' (a : WithTop α) : a * ⊤ = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> simp [mul_def] <;> 

Proof state:
case top
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
⊢ Option.map₂ (fun x x_1 => x * x_1) ⊤ ⊤ = ⊤

Next tactic:
rfl
theorem mul_top' (a : WithTop α) : a * ⊤ = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> simp [mul_def] <;> 

Proof state:
case coe
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a✝ : α
⊢ (if a✝ = 0 then 0 else Option.map₂ (fun x x_1 => x * x_1) ↑a✝ ⊤) = if a✝ = 0 then 0 else ⊤

Next tactic:
rfl
@[simp] theorem mul_top {a : WithTop α} (h : a ≠ 0) : a * ⊤ = ⊤ := by 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a : WithTop α
h : a ≠ 0
⊢ a * ⊤ = ⊤

Next tactic:
rw [mul_top', if_neg h]
theorem top_mul' (a : WithTop α) : ⊤ * a = if a = 0 then 0 else ⊤ := by
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a : WithTop α
⊢ ⊤ * a = if a = 0 then 0 else ⊤

Next tactic:
induction a using recTopCoe
theorem top_mul' (a : WithTop α) : ⊤ * a = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> 

Proof state:
case top
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
⊢ ⊤ * ⊤ = if ⊤ = 0 then 0 else ⊤

Next tactic:
simp [mul_def]
theorem top_mul' (a : WithTop α) : ⊤ * a = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> 

Proof state:
case coe
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a✝ : α
⊢ ⊤ * ↑a✝ = if ↑a✝ = 0 then 0 else ⊤

Next tactic:
simp [mul_def]
theorem top_mul' (a : WithTop α) : ⊤ * a = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> simp [mul_def] <;> 

Proof state:
case top
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
⊢ Option.map₂ (fun x x_1 => x * x_1) ⊤ ⊤ = ⊤

Next tactic:
rfl
theorem top_mul' (a : WithTop α) : ⊤ * a = if a = 0 then 0 else ⊤ := by
  induction a using recTopCoe <;> simp [mul_def] <;> 

Proof state:
case coe
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a✝ : α
⊢ (if a✝ = 0 then 0 else Option.map₂ (fun x x_1 => x * x_1) ⊤ ↑a✝) = if a✝ = 0 then 0 else ⊤

Next tactic:
rfl
@[simp] theorem top_mul {a : WithTop α} (h : a ≠ 0) : ⊤ * a = ⊤ := by 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a : WithTop α
h : a ≠ 0
⊢ ⊤ * a = ⊤

Next tactic:
rw [top_mul', if_neg h]
theorem mul_eq_top_iff {a b : WithTop α} : a * b = ⊤ ↔ a ≠ 0 ∧ b = ⊤ ∨ a = ⊤ ∧ b ≠ 0 := by
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a b : WithTop α
⊢ a * b = ⊤ ↔ a ≠ 0 ∧ b = ⊤ ∨ a = ⊤ ∧ b ≠ 0

Next tactic:
rw [mul_def, ite_eq_iff, ← none_eq_top, Option.map₂_eq_none_iff]
theorem mul_eq_top_iff {a b : WithTop α} : a * b = ⊤ ↔ a ≠ 0 ∧ b = ⊤ ∨ a = ⊤ ∧ b ≠ 0 := by
  rw [mul_def, ite_eq_iff, ← none_eq_top, Option.map₂_eq_none_iff]
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a b : WithTop α
⊢ (a = 0 ∨ b = 0) ∧ 0 = none ∨ ¬(a = 0 ∨ b = 0) ∧ (a = none ∨ b = none) ↔ a ≠ 0 ∧ b = none ∨ a = none ∧ b ≠ 0

Next tactic:
have ha : a = 0 → a ≠ none := fun h => h.symm ▸ zero_ne_top
theorem mul_eq_top_iff {a b : WithTop α} : a * b = ⊤ ↔ a ≠ 0 ∧ b = ⊤ ∨ a = ⊤ ∧ b ≠ 0 := by
  rw [mul_def, ite_eq_iff, ← none_eq_top, Option.map₂_eq_none_iff]
  have ha : a = 0 → a ≠ none := fun h => h.symm ▸ zero_ne_top
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a b : WithTop α
ha : a = 0 → a ≠ none
⊢ (a = 0 ∨ b = 0) ∧ 0 = none ∨ ¬(a = 0 ∨ b = 0) ∧ (a = none ∨ b = none) ↔ a ≠ 0 ∧ b = none ∨ a = none ∧ b ≠ 0

Next tactic:
have hb : b = 0 → b ≠ none := fun h => h.symm ▸ zero_ne_top
theorem mul_eq_top_iff {a b : WithTop α} : a * b = ⊤ ↔ a ≠ 0 ∧ b = ⊤ ∨ a = ⊤ ∧ b ≠ 0 := by
  rw [mul_def, ite_eq_iff, ← none_eq_top, Option.map₂_eq_none_iff]
  have ha : a = 0 → a ≠ none := fun h => h.symm ▸ zero_ne_top
  have hb : b = 0 → b ≠ none := fun h => h.symm ▸ zero_ne_top
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : Zero α
inst✝ : Mul α
a b : WithTop α
ha : a = 0 → a ≠ none
hb : b = 0 → b ≠ none
⊢ (a = 0 ∨ b = 0) ∧ 0 = none ∨ ¬(a = 0 ∨ b = 0) ∧ (a = none ∨ b = none) ↔ a ≠ 0 ∧ b = none ∨ a = none ∧ b ≠ 0

Next tactic:
tauto
theorem mul_lt_top' [LT α] {a b : WithTop α} (ha : a < ⊤) (hb : b < ⊤) : a * b < ⊤ := by
  

Proof state:
α : Type u_1
inst✝³ : DecidableEq α
inst✝² : Zero α
inst✝¹ : Mul α
inst✝ : LT α
a b : WithTop α
ha : a < ⊤
hb : b < ⊤
⊢ a * b < ⊤

Next tactic:
rw [WithTop.lt_top_iff_ne_top] at *
theorem mul_lt_top' [LT α] {a b : WithTop α} (ha : a < ⊤) (hb : b < ⊤) : a * b < ⊤ := by
  rw [WithTop.lt_top_iff_ne_top] at *
  

Proof state:
α : Type u_1
inst✝³ : DecidableEq α
inst✝² : Zero α
inst✝¹ : Mul α
inst✝ : LT α
a b : WithTop α
ha : a ≠ ⊤
hb : b ≠ ⊤
⊢ a * b ≠ ⊤

Next tactic:
simp only [Ne.def, mul_eq_top_iff, *, and_false, false_and, or_self, not_false_eq_true]
instance noZeroDivisors [NoZeroDivisors α] : NoZeroDivisors (WithTop α) := by
  

Proof state:
α : Type u_1
inst✝³ : DecidableEq α
inst✝² : Zero α
inst✝¹ : Mul α
inst✝ : NoZeroDivisors α
⊢ NoZeroDivisors (WithTop α)

Next tactic:
refine ⟨fun h₁ => Decidable.by_contradiction <| fun h₂ => ?_⟩
instance noZeroDivisors [NoZeroDivisors α] : NoZeroDivisors (WithTop α) := by
  refine ⟨fun h₁ => Decidable.by_contradiction <| fun h₂ => ?_⟩
  

Proof state:
α : Type u_1
inst✝³ : DecidableEq α
inst✝² : Zero α
inst✝¹ : Mul α
inst✝ : NoZeroDivisors α
a✝ b✝ : WithTop α
h₁ : a✝ * b✝ = 0
h₂ : ¬(a✝ = 0 ∨ b✝ = 0)
⊢ False

Next tactic:
rw [mul_def, if_neg h₂] at h₁
instance noZeroDivisors [NoZeroDivisors α] : NoZeroDivisors (WithTop α) := by
  refine ⟨fun h₁ => Decidable.by_contradiction <| fun h₂ => ?_⟩
  rw [mul_def, if_neg h₂] at h₁
  

Proof state:
α : Type u_1
inst✝³ : DecidableEq α
inst✝² : Zero α
inst✝¹ : Mul α
inst✝ : NoZeroDivisors α
a✝ b✝ : WithTop α
h₁ : Option.map₂ (fun x x_1 => x * x_1) a✝ b✝ = 0
h₂ : ¬(a✝ = 0 ∨ b✝ = 0)
⊢ False

Next tactic:
rcases Option.mem_map₂_iff.1 h₁ with ⟨a, b, (rfl : _ = _), (rfl : _ = _), hab⟩
instance noZeroDivisors [NoZeroDivisors α] : NoZeroDivisors (WithTop α) := by
  refine ⟨fun h₁ => Decidable.by_contradiction <| fun h₂ => ?_⟩
  rw [mul_def, if_neg h₂] at h₁
  rcases Option.mem_map₂_iff.1 h₁ with ⟨a, b, (rfl : _ = _), (rfl : _ = _), hab⟩
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
inst✝³ : DecidableEq α
inst✝² : Zero α
inst✝¹ : Mul α
inst✝ : NoZeroDivisors α
a b : α
hab : a * b = 0
h₁ : Option.map₂ (fun x x_1 => x * x_1) (Option.some a) (Option.some b) = 0
h₂ : ¬(Option.some a = 0 ∨ Option.some b = 0)
⊢ False

Next tactic:
exact h₂ ((eq_zero_or_eq_zero_of_mul_eq_zero hab).imp (congr_arg some) (congr_arg some))
@[simp, norm_cast]
theorem coe_mul {a b : α} : (↑(a * b) : WithTop α) = a * b := by
  

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : α
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
by_cases ha : a = 0
@[simp, norm_cast]
theorem coe_mul {a b : α} : (↑(a * b) : WithTop α) = a * b := by
  by_cases ha : a = 0
  · 

Proof state:
case pos
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : α
ha : a = 0
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
simp [ha]
@[simp, norm_cast]
theorem coe_mul {a b : α} : (↑(a * b) : WithTop α) = a * b := by
  by_cases ha : a = 0
  · simp [ha]
  · 

Proof state:
case neg
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : α
ha : ¬a = 0
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
by_cases hb : b = 0
@[simp, norm_cast]
theorem coe_mul {a b : α} : (↑(a * b) : WithTop α) = a * b := by
  by_cases ha : a = 0
  · simp [ha]
  · by_cases hb : b = 0
    · 

Proof state:
case pos
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : α
ha : ¬a = 0
hb : b = 0
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
simp [hb]
@[simp, norm_cast]
theorem coe_mul {a b : α} : (↑(a * b) : WithTop α) = a * b := by
  by_cases ha : a = 0
  · simp [ha]
  · by_cases hb : b = 0
    · simp [hb]
    · 

Proof state:
case neg
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : α
ha : ¬a = 0
hb : ¬b = 0
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
simp [*, mul_def]
@[simp, norm_cast]
theorem coe_mul {a b : α} : (↑(a * b) : WithTop α) = a * b := by
  by_cases ha : a = 0
  · simp [ha]
  · by_cases hb : b = 0
    · simp [hb]
    · simp [*, mul_def]
      

Proof state:
case neg
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : α
ha : ¬a = 0
hb : ¬b = 0
⊢ ↑(a * b) = Option.map₂ (fun x x_1 => x * x_1) ↑a ↑b

Next tactic:
rfl
theorem mul_coe {b : α} (hb : b ≠ 0) : ∀ {a : WithTop α},
    a * (b : WithTop α) = a.bind fun a : α => ↑(a * b)
  | none =>
    show (if (⊤ : WithTop α) = 0 ∨ (b : WithTop α) = 0 then 0 else ⊤ : WithTop α) = ⊤ by 

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
b : α
hb : b ≠ 0
⊢ (if ⊤ = 0 ∨ ↑b = 0 then 0 else ⊤) = ⊤

Next tactic:
simp [hb]
theorem mul_coe {b : α} (hb : b ≠ 0) : ∀ {a : WithTop α},
    a * (b : WithTop α) = a.bind fun a : α => ↑(a * b)
  | none =>
    show (if (⊤ : WithTop α) = 0 ∨ (b : WithTop α) = 0 then 0 else ⊤ : WithTop α) = ⊤ by simp [hb]
  | Option.some a => by
    

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
b : α
hb : b ≠ 0
a : α
⊢ Option.some a * ↑b = Option.bind (Option.some a) fun a => Option.some (a * b)

Next tactic:
rw [some_eq_coe, ← coe_mul]
theorem mul_coe {b : α} (hb : b ≠ 0) : ∀ {a : WithTop α},
    a * (b : WithTop α) = a.bind fun a : α => ↑(a * b)
  | none =>
    show (if (⊤ : WithTop α) = 0 ∨ (b : WithTop α) = 0 then 0 else ⊤ : WithTop α) = ⊤ by simp [hb]
  | Option.some a => by
    rw [some_eq_coe, ← coe_mul]
    

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
b : α
hb : b ≠ 0
a : α
⊢ ↑(a * b) = Option.bind ↑a fun a => Option.some (a * b)

Next tactic:
rfl
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : WithTop α
⊢ untop' 0 (a * b) = untop' 0 a * untop' 0 b

Next tactic:
by_cases ha : a = 0
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · 

Proof state:
case pos
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : WithTop α
ha : a = 0
⊢ untop' 0 (a * b) = untop' 0 a * untop' 0 b

Next tactic:
rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
  

Proof state:
case neg
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : WithTop α
ha : ¬a = 0
⊢ untop' 0 (a * b) = untop' 0 a * untop' 0 b

Next tactic:
by_cases hb : b = 0
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
  by_cases hb : b = 0; · 

Proof state:
case pos
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : WithTop α
ha : ¬a = 0
hb : b = 0
⊢ untop' 0 (a * b) = untop' 0 a * untop' 0 b

Next tactic:
rw [hb, mul_zero, ← coe_zero, untop'_coe, mul_zero]
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
  by_cases hb : b = 0; · rw [hb, mul_zero, ← coe_zero, untop'_coe, mul_zero]
  

Proof state:
case neg
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a b : WithTop α
ha : ¬a = 0
hb : ¬b = 0
⊢ untop' 0 (a * b) = untop' 0 a * untop' 0 b

Next tactic:
induction a using WithTop.recTopCoe
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
  by_cases hb : b = 0; · rw [hb, mul_zero, ← coe_zero, untop'_coe, mul_zero]
  induction a using WithTop.recTopCoe; · 

Proof state:
case neg.top
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
b : WithTop α
hb : ¬b = 0
ha : ¬⊤ = 0
⊢ untop' 0 (⊤ * b) = untop' 0 ⊤ * untop' 0 b

Next tactic:
rw [top_mul hb, untop'_top, zero_mul]
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
  by_cases hb : b = 0; · rw [hb, mul_zero, ← coe_zero, untop'_coe, mul_zero]
  induction a using WithTop.recTopCoe; · rw [top_mul hb, untop'_top, zero_mul]
  

Proof state:
case neg.coe
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
b : WithTop α
hb : ¬b = 0
a✝ : α
ha : ¬↑a✝ = 0
⊢ untop' 0 (↑a✝ * b) = untop' 0 ↑a✝ * untop' 0 b

Next tactic:
induction b using WithTop.recTopCoe
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
  by_cases hb : b = 0; · rw [hb, mul_zero, ← coe_zero, untop'_coe, mul_zero]
  induction a using WithTop.recTopCoe; · rw [top_mul hb, untop'_top, zero_mul]
  induction b using WithTop.recTopCoe; · 

Proof state:
case neg.coe.top
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a✝ : α
ha : ¬↑a✝ = 0
hb : ¬⊤ = 0
⊢ untop' 0 (↑a✝ * ⊤) = untop' 0 ↑a✝ * untop' 0 ⊤

Next tactic:
rw [mul_top ha, untop'_top, mul_zero]
@[simp]
theorem untop'_zero_mul (a b : WithTop α) : (a * b).untop' 0 = a.untop' 0 * b.untop' 0 := by
  by_cases ha : a = 0; · rw [ha, zero_mul, ← coe_zero, untop'_coe, zero_mul]
  by_cases hb : b = 0; · rw [hb, mul_zero, ← coe_zero, untop'_coe, mul_zero]
  induction a using WithTop.recTopCoe; · rw [top_mul hb, untop'_top, zero_mul]
  induction b using WithTop.recTopCoe; · rw [mul_top ha, untop'_top, mul_zero]
  

Proof state:
case neg.coe.coe
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : MulZeroClass α
a✝¹ : α
ha : ¬↑a✝¹ = 0
a✝ : α
hb : ¬↑a✝ = 0
⊢ untop' 0 (↑a✝¹ * ↑a✝) = untop' 0 ↑a✝¹ * untop' 0 ↑a✝

Next tactic:
rw [← coe_mul, untop'_coe, untop'_coe, untop'_coe]
/-- `Nontrivial α` is needed here as otherwise we have `1 * ⊤ = ⊤` but also `0 * ⊤ = 0`. -/
instance instMulZeroOneClassWithTop [MulZeroOneClass α] [Nontrivial α] :
    MulZeroOneClass (WithTop α) :=
  { WithTop.instMulZeroClassWithTop with
    one_mul := fun a =>
      match a with
      | ⊤ => mul_top (mt coe_eq_coe.1 one_ne_zero)
      | (a : α) => by 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : MulZeroOneClass α
inst✝ : Nontrivial α
src✝ : MulZeroClass (WithTop α) := instMulZeroClassWithTop
a✝ : WithTop α
a : α
⊢ 1 * ↑a = ↑a

Next tactic:
rw [← coe_one, ← coe_mul, one_mul]
/-- `Nontrivial α` is needed here as otherwise we have `1 * ⊤ = ⊤` but also `0 * ⊤ = 0`. -/
instance instMulZeroOneClassWithTop [MulZeroOneClass α] [Nontrivial α] :
    MulZeroOneClass (WithTop α) :=
  { WithTop.instMulZeroClassWithTop with
    one_mul := fun a =>
      match a with
      | ⊤ => mul_top (mt coe_eq_coe.1 one_ne_zero)
      | (a : α) => by rw [← coe_one, ← coe_mul, one_mul],
    mul_one := fun a =>
      match a with
      | ⊤ => top_mul (mt coe_eq_coe.1 one_ne_zero)
      | (a : α) => by 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : MulZeroOneClass α
inst✝ : Nontrivial α
src✝ : MulZeroClass (WithTop α) := instMulZeroClassWithTop
a✝ : WithTop α
a : α
⊢ ↑a * 1 = ↑a

Next tactic:
rw [← coe_one, ← coe_mul, mul_one]
/-- A version of `WithTop.map` for `MonoidWithZeroHom`s. -/
@[simps (config := .asFn)]
protected def _root_.MonoidWithZeroHom.withTopMap {R S : Type*} [MulZeroOneClass R] [DecidableEq R]
    [Nontrivial R] [MulZeroOneClass S] [DecidableEq S] [Nontrivial S] (f : R →*₀ S)
    (hf : Function.Injective f) : WithTop R →*₀ WithTop S :=
  { f.toZeroHom.withTopMap, f.toMonoidHom.toOneHom.withTopMap with
    toFun := WithTop.map f
    map_mul' := fun x y => by
      

Proof state:
α : Type u_1
inst✝⁶ : DecidableEq α
R : Type u_2
S : Type u_3
inst✝⁵ : MulZeroOneClass R
inst✝⁴ : DecidableEq R
inst✝³ : Nontrivial R
inst✝² : MulZeroOneClass S
inst✝¹ : DecidableEq S
inst✝ : Nontrivial S
f : R →*₀ S
hf : Function.Injective ⇑f
src✝¹ : ZeroHom (WithTop R) (WithTop S) := ZeroHom.withTopMap ↑f
src✝ : OneHom (WithTop R) (WithTop S) := OneHom.withTopMap ↑↑f
x y : WithTop R
⊢ ZeroHom.toFun { toFun := map ⇑f, map_zero' := (_ : ZeroHom.toFun src✝¹ 0 = 0) } (x * y) =
    ZeroHom.toFun { toFun := map ⇑f, map_zero' := (_ : ZeroHom.toFun src✝¹ 0 = 0) } x *
      ZeroHom.toFun { toFun := map ⇑f, map_zero' := (_ : ZeroHom.toFun src✝¹ 0 = 0) } y

Next tactic:
have : ∀ z, map f z = 0 ↔ z = 0 := fun z =>
        (Option.map_injective hf).eq_iff' f.toZeroHom.withTopMap.map_zero