l3lab/ntp-mathlib huggingface dataset:
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
⊢ False

Next tactic:
classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
      apply_fun fun e => (e y).down at H
      dsimp [LocallyConstant.ofIsClopen] at H
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      erw [ContinuousMap.coe_mk, ContinuousMap.coe_mk, Function.comp_apply, if_pos hyV] at H
      exact top_ne_bot H
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
⊢ False

Next tactic:
let Z := of (ULift.{u} <| Fin 2)
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
⊢ False

Next tactic:
let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
⊢ False

Next tactic:
let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
⊢ False

Next tactic:
have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
⊢ h = g

Next tactic:
rw [← cancel_epi f]
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
⊢ f ≫ h = f ≫ g

Next tactic:
ext x
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        

Proof state:
case w
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
x : (forget Profinite).obj X
⊢ (f ≫ h) x = (f ≫ g) x

Next tactic:
apply ULift.ext
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        

Proof state:
case w.h
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
x : (forget Profinite).obj X
⊢ ((f ≫ h) x).down = ((f ≫ g) x).down

Next tactic:
dsimp [LocallyConstant.ofIsClopen]
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        

Proof state:
case w.h
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
x : (forget Profinite).obj X
⊢ ((f ≫ ContinuousMap.mk fun x => { down := 1 }) x).down =
    ((f ≫ ContinuousMap.mk (ULift.up ∘ fun x => if x ∈ V then 0 else 1)) x).down

Next tactic:
erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        

Proof state:
case w.h.hnc
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
x : (forget Profinite).obj X
⊢ f x ∉ V

Next tactic:
refine' mt (fun α => hVU α) _
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        

Proof state:
case w.h.hnc
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
x : (forget Profinite).obj X
⊢ f x ∉ U

Next tactic:
simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
H : h = g
⊢ False

Next tactic:
apply_fun fun e => (e y).down at H
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
      apply_fun fun e => (e y).down at H
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
H : (h y).down = (g y).down
⊢ False

Next tactic:
dsimp [LocallyConstant.ofIsClopen] at H