l3lab/ntp-mathlib huggingface dataset:
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
⊢ IsCoseparator (G ⨯ H) ↔ IsCoseparating {G, H}

Next tactic:
refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · 

Proof state:
case refine'_1
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
h : IsCoseparator (G ⨯ H)
X Y : C
u v : X ⟶ Y
huv : ∀ G_1 ∈ {G, H}, ∀ (h : Y ⟶ G_1), u ≫ h = v ≫ h
⊢ u = v

Next tactic:
refine' h.def _ _ fun g => prod.hom_ext _ _
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · 

Proof state:
case refine'_1.refine'_1
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
h : IsCoseparator (G ⨯ H)
X Y : C
u v : X ⟶ Y
huv : ∀ G_1 ∈ {G, H}, ∀ (h : Y ⟶ G_1), u ≫ h = v ≫ h
g : Y ⟶ G ⨯ H
⊢ (u ≫ g) ≫ prod.fst = (v ≫ g) ≫ prod.fst

Next tactic:
simpa using huv G (by simp) (g ≫ Limits.prod.fst)
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · simpa using huv G (by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
h : IsCoseparator (G ⨯ H)
X Y : C
u v : X ⟶ Y
huv : ∀ G_1 ∈ {G, H}, ∀ (h : Y ⟶ G_1), u ≫ h = v ≫ h
g : Y ⟶ G ⨯ H
⊢ G ∈ {G, H}

Next tactic:
simp
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · simpa using huv G (by simp) (g ≫ Limits.prod.fst)
    · 

Proof state:
case refine'_1.refine'_2
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
h : IsCoseparator (G ⨯ H)
X Y : C
u v : X ⟶ Y
huv : ∀ G_1 ∈ {G, H}, ∀ (h : Y ⟶ G_1), u ≫ h = v ≫ h
g : Y ⟶ G ⨯ H
⊢ (u ≫ g) ≫ prod.snd = (v ≫ g) ≫ prod.snd

Next tactic:
simpa using huv H (by simp) (g ≫ Limits.prod.snd)
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · simpa using huv G (by simp) (g ≫ Limits.prod.fst)
    · simpa using huv H (by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
h : IsCoseparator (G ⨯ H)
X Y : C
u v : X ⟶ Y
huv : ∀ G_1 ∈ {G, H}, ∀ (h : Y ⟶ G_1), u ≫ h = v ≫ h
g : Y ⟶ G ⨯ H
⊢ H ∈ {G, H}

Next tactic:
simp
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · simpa using huv G (by simp) (g ≫ Limits.prod.fst)
    · simpa using huv H (by simp) (g ≫ Limits.prod.snd)
  · 

Proof state:
case refine'_2
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
h : IsCoseparating {G, H}
X Y : C
u v : X ⟶ Y
huv : ∀ (h : Y ⟶ G ⨯ H), u ≫ h = v ≫ h
Z : C
hZ : Z ∈ {G, H}
g : Y ⟶ Z
⊢ u ≫ g = v ≫ g

Next tactic:
simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hZ
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · simpa using huv G (by simp) (g ≫ Limits.prod.fst)
    · simpa using huv H (by simp) (g ≫ Limits.prod.snd)
  · simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hZ
    

Proof state:
case refine'_2
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
h : IsCoseparating {G, H}
X Y : C
u v : X ⟶ Y
huv : ∀ (h : Y ⟶ G ⨯ H), u ≫ h = v ≫ h
Z : C
g : Y ⟶ Z
hZ : Z = G ∨ Z = H
⊢ u ≫ g = v ≫ g

Next tactic:
rcases hZ with (rfl | rfl)
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · simpa using huv G (by simp) (g ≫ Limits.prod.fst)
    · simpa using huv H (by simp) (g ≫ Limits.prod.snd)
  · simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hZ
    rcases hZ with (rfl | rfl)
    · 

Proof state:
case refine'_2.inl
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
H X Y : C
u v : X ⟶ Y
Z : C
g : Y ⟶ Z
inst✝ : HasBinaryProduct Z H
h : IsCoseparating {Z, H}
huv : ∀ (h : Y ⟶ Z ⨯ H), u ≫ h = v ≫ h
⊢ u ≫ g = v ≫ g

Next tactic:
simpa using huv (prod.lift g 0) =≫ Limits.prod.fst
theorem isCoseparator_prod (G H : C) [HasBinaryProduct G H] :
    IsCoseparator (G ⨯ H) ↔ IsCoseparating ({G, H} : Set C) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => prod.hom_ext _ _
    · simpa using huv G (by simp) (g ≫ Limits.prod.fst)
    · simpa using huv H (by simp) (g ≫ Limits.prod.snd)
  · simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hZ
    rcases hZ with (rfl | rfl)
    · simpa using huv (prod.lift g 0) =≫ Limits.prod.fst
    · 

Proof state:
case refine'_2.inr
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G X Y : C
u v : X ⟶ Y
Z : C
g : Y ⟶ Z
inst✝ : HasBinaryProduct G Z
h : IsCoseparating {G, Z}
huv : ∀ (h : Y ⟶ G ⨯ Z), u ≫ h = v ≫ h
⊢ u ≫ g = v ≫ g

Next tactic:
simpa using huv (prod.lift 0 g) =≫ Limits.prod.snd
theorem isCoseparator_prod_of_isCoseparator_left (G H : C) [HasBinaryProduct G H]
    (hG : IsCoseparator G) : IsCoseparator (G ⨯ H) :=
  (isCoseparator_prod _ _).2 <| IsCoseparating.mono hG <| by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
hG : IsCoseparator G
⊢ {G} ⊆ {G, H}

Next tactic:
simp
theorem isCoseparator_prod_of_isCoseparator_right (G H : C) [HasBinaryProduct G H]
    (hH : IsCoseparator H) : IsCoseparator (G ⨯ H) :=
  (isCoseparator_prod _ _).2 <| IsCoseparating.mono hH <| by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
G H : C
inst✝ : HasBinaryProduct G H
hH : IsCoseparator H
⊢ {H} ⊆ {G, H}

Next tactic:
simp
theorem isCoseparator_pi {β : Type w} (f : β → C) [HasProduct f] :
    IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f) := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
⊢ IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f)

Next tactic:
refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
theorem isCoseparator_pi {β : Type w} (f : β → C) [HasProduct f] :
    IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · 

Proof state:
case refine'_1
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
h : IsCoseparator (∏ f)
X Y : C
u v : X ⟶ Y
huv : ∀ G ∈ Set.range f, ∀ (h : Y ⟶ G), u ≫ h = v ≫ h
⊢ u = v

Next tactic:
refine' h.def _ _ fun g => limit.hom_ext fun b => _
theorem isCoseparator_pi {β : Type w} (f : β → C) [HasProduct f] :
    IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => limit.hom_ext fun b => _
    

Proof state:
case refine'_1
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
h : IsCoseparator (∏ f)
X Y : C
u v : X ⟶ Y
huv : ∀ G ∈ Set.range f, ∀ (h : Y ⟶ G), u ≫ h = v ≫ h
g : Y ⟶ ∏ f
b : Discrete β
⊢ (u ≫ g) ≫ limit.π (Discrete.functor f) b = (v ≫ g) ≫ limit.π (Discrete.functor f) b

Next tactic:
simpa using huv (f b.as) (by simp) (g ≫ limit.π (Discrete.functor f) _)
theorem isCoseparator_pi {β : Type w} (f : β → C) [HasProduct f] :
    IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => limit.hom_ext fun b => _
    simpa using huv (f b.as) (by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
h : IsCoseparator (∏ f)
X Y : C
u v : X ⟶ Y
huv : ∀ G ∈ Set.range f, ∀ (h : Y ⟶ G), u ≫ h = v ≫ h
g : Y ⟶ ∏ f
b : Discrete β
⊢ f b.as ∈ Set.range f

Next tactic:
simp
theorem isCoseparator_pi {β : Type w} (f : β → C) [HasProduct f] :
    IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => limit.hom_ext fun b => _
    simpa using huv (f b.as) (by simp) (g ≫ limit.π (Discrete.functor f) _)
  · 

Proof state:
case refine'_2
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
h : IsCoseparating (Set.range f)
X Y : C
u v : X ⟶ Y
huv : ∀ (h : Y ⟶ ∏ f), u ≫ h = v ≫ h
Z : C
hZ : Z ∈ Set.range f
g : Y ⟶ Z
⊢ u ≫ g = v ≫ g

Next tactic:
obtain ⟨b, rfl⟩ := Set.mem_range.1 hZ
theorem isCoseparator_pi {β : Type w} (f : β → C) [HasProduct f] :
    IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => limit.hom_ext fun b => _
    simpa using huv (f b.as) (by simp) (g ≫ limit.π (Discrete.functor f) _)
  · obtain ⟨b, rfl⟩ := Set.mem_range.1 hZ
    

Proof state:
case refine'_2.intro
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
h : IsCoseparating (Set.range f)
X Y : C
u v : X ⟶ Y
huv : ∀ (h : Y ⟶ ∏ f), u ≫ h = v ≫ h
b : β
hZ : f b ∈ Set.range f
g : Y ⟶ f b
⊢ u ≫ g = v ≫ g

Next tactic:
classical simpa using huv (Pi.lift (Pi.single b g)) =≫ Pi.π f b
theorem isCoseparator_pi {β : Type w} (f : β → C) [HasProduct f] :
    IsCoseparator (∏ f) ↔ IsCoseparating (Set.range f) := by
  refine'
    ⟨fun h X Y u v huv => _, fun h =>
      (isCoseparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => _⟩
  · refine' h.def _ _ fun g => limit.hom_ext fun b => _
    simpa using huv (f b.as) (by simp) (g ≫ limit.π (Discrete.functor f) _)
  · obtain ⟨b, rfl⟩ := Set.mem_range.1 hZ
    classical 

Proof state:
case refine'_2.intro
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
h : IsCoseparating (Set.range f)
X Y : C
u v : X ⟶ Y
huv : ∀ (h : Y ⟶ ∏ f), u ≫ h = v ≫ h
b : β
hZ : f b ∈ Set.range f
g : Y ⟶ f b
⊢ u ≫ g = v ≫ g

Next tactic:
simpa using huv (Pi.lift (Pi.single b g)) =≫ Pi.π f b
theorem isCoseparator_pi_of_isCoseparator {β : Type w} (f : β → C) [HasProduct f] (b : β)
    (hb : IsCoseparator (f b)) : IsCoseparator (∏ f) :=
  (isCoseparator_pi _).2 <| IsCoseparating.mono hb <| by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasZeroMorphisms C
β : Type w
f : β → C
inst✝ : HasProduct f
b : β
hb : IsCoseparator (f b)
⊢ {f b} ⊆ Set.range f

Next tactic:
simp
theorem isDetector_iff_reflectsIsomorphisms_coyoneda_obj (G : C) :
    IsDetector G ↔ ReflectsIsomorphisms (coyoneda.obj (op G)) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
⊢ IsDetector G ↔ ReflectsIsomorphisms (coyoneda.obj (op G))

Next tactic:
refine'
    ⟨fun hG => ⟨fun f hf => hG.def _ fun h => _⟩, fun h =>
      (isDetector_def _).2 fun X Y f hf => _⟩
theorem isDetector_iff_reflectsIsomorphisms_coyoneda_obj (G : C) :
    IsDetector G ↔ ReflectsIsomorphisms (coyoneda.obj (op G)) := by
  refine'
    ⟨fun hG => ⟨fun f hf => hG.def _ fun h => _⟩, fun h =>
      (isDetector_def _).2 fun X Y f hf => _⟩
  · 

Proof state:
case refine'_1
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
hG : IsDetector G
A✝ B✝ : C
f : A✝ ⟶ B✝
hf : IsIso ((coyoneda.obj (op G)).map f)
h : G ⟶ B✝
⊢ ∃! h', h' ≫ f = h

Next tactic:
rw [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
theorem isDetector_iff_reflectsIsomorphisms_coyoneda_obj (G : C) :
    IsDetector G ↔ ReflectsIsomorphisms (coyoneda.obj (op G)) := by
  refine'
    ⟨fun hG => ⟨fun f hf => hG.def _ fun h => _⟩, fun h =>
      (isDetector_def _).2 fun X Y f hf => _⟩
  · rw [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
    

Proof state:
case refine'_1
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
hG : IsDetector G
A✝ B✝ : C
f : A✝ ⟶ B✝
hf : ∀ (b : (coyoneda.obj (op G)).obj B✝), ∃! a, (coyoneda.obj (op G)).map f a = b
h : G ⟶ B✝
⊢ ∃! h', h' ≫ f = h

Next tactic:
exact hf h
theorem isDetector_iff_reflectsIsomorphisms_coyoneda_obj (G : C) :
    IsDetector G ↔ ReflectsIsomorphisms (coyoneda.obj (op G)) := by
  refine'
    ⟨fun hG => ⟨fun f hf => hG.def _ fun h => _⟩, fun h =>
      (isDetector_def _).2 fun X Y f hf => _⟩
  · rw [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
    exact hf h
  · 

Proof state:
case refine'_2
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
h : ReflectsIsomorphisms (coyoneda.obj (op G))
X Y : C
f : X ⟶ Y
hf : ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
⊢ IsIso f

Next tactic:
suffices IsIso ((coyoneda.obj (op G)).map f) by
      exact @isIso_of_reflects_iso _ _ _ _ _ _ _ (coyoneda.obj (op G)) _ h
theorem isDetector_iff_reflectsIsomorphisms_coyoneda_obj (G : C) :
    IsDetector G ↔ ReflectsIsomorphisms (coyoneda.obj (op G)) := by
  refine'
    ⟨fun hG => ⟨fun f hf => hG.def _ fun h => _⟩, fun h =>
      (isDetector_def _).2 fun X Y f hf => _⟩
  · rw [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
    exact hf h
  · suffices IsIso ((coyoneda.obj (op G)).map f) by
      

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
h : ReflectsIsomorphisms (coyoneda.obj (op G))
X Y : C
f : X ⟶ Y
hf : ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
this : IsIso ((coyoneda.obj (op G)).map f)
⊢ IsIso f

Next tactic:
exact @isIso_of_reflects_iso _ _ _ _ _ _ _ (coyoneda.obj (op G)) _ h
theorem isDetector_iff_reflectsIsomorphisms_coyoneda_obj (G : C) :
    IsDetector G ↔ ReflectsIsomorphisms (coyoneda.obj (op G)) := by
  refine'
    ⟨fun hG => ⟨fun f hf => hG.def _ fun h => _⟩, fun h =>
      (isDetector_def _).2 fun X Y f hf => _⟩
  · rw [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
    exact hf h
  · suffices IsIso ((coyoneda.obj (op G)).map f) by
      exact @isIso_of_reflects_iso _ _ _ _ _ _ _ (coyoneda.obj (op G)) _ h
    

Proof state:
case refine'_2
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
h : ReflectsIsomorphisms (coyoneda.obj (op G))
X Y : C
f : X ⟶ Y
hf : ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
⊢ IsIso ((coyoneda.obj (op G)).map f)

Next tactic:
rwa [isIso_iff_bijective, Function.bijective_iff_existsUnique]
theorem isCodetector_iff_reflectsIsomorphisms_yoneda_obj (G : C) :
    IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
⊢ IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G)

Next tactic:
refine' ⟨fun hG => ⟨fun f hf => _⟩, fun h => (isCodetector_def _).2 fun X Y f hf => _⟩
theorem isCodetector_iff_reflectsIsomorphisms_yoneda_obj (G : C) :
    IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G) := by
  refine' ⟨fun hG => ⟨fun f hf => _⟩, fun h => (isCodetector_def _).2 fun X Y f hf => _⟩
  · 

Proof state:
case refine'_1
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
hG : IsCodetector G
A✝ B✝ : Cᵒᵖ
f : A✝ ⟶ B✝
hf : IsIso ((yoneda.obj G).map f)
⊢ IsIso f

Next tactic:
refine' (isIso_unop_iff _).1 (hG.def _ _)
theorem isCodetector_iff_reflectsIsomorphisms_yoneda_obj (G : C) :
    IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G) := by
  refine' ⟨fun hG => ⟨fun f hf => _⟩, fun h => (isCodetector_def _).2 fun X Y f hf => _⟩
  · refine' (isIso_unop_iff _).1 (hG.def _ _)
    

Proof state:
case refine'_1
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
hG : IsCodetector G
A✝ B✝ : Cᵒᵖ
f : A✝ ⟶ B✝
hf : IsIso ((yoneda.obj G).map f)
⊢ ∀ (h : B✝.unop ⟶ G), ∃! h', f.unop ≫ h' = h

Next tactic:
rwa [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
theorem isCodetector_iff_reflectsIsomorphisms_yoneda_obj (G : C) :
    IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G) := by
  refine' ⟨fun hG => ⟨fun f hf => _⟩, fun h => (isCodetector_def _).2 fun X Y f hf => _⟩
  · refine' (isIso_unop_iff _).1 (hG.def _ _)
    rwa [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
  · 

Proof state:
case refine'_2
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
h : ReflectsIsomorphisms (yoneda.obj G)
X Y : C
f : X ⟶ Y
hf : ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
⊢ IsIso f

Next tactic:
rw [← isIso_op_iff]
theorem isCodetector_iff_reflectsIsomorphisms_yoneda_obj (G : C) :
    IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G) := by
  refine' ⟨fun hG => ⟨fun f hf => _⟩, fun h => (isCodetector_def _).2 fun X Y f hf => _⟩
  · refine' (isIso_unop_iff _).1 (hG.def _ _)
    rwa [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
  · rw [← isIso_op_iff]
    

Proof state:
case refine'_2
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
h : ReflectsIsomorphisms (yoneda.obj G)
X Y : C
f : X ⟶ Y
hf : ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
⊢ IsIso f.op

Next tactic:
suffices IsIso ((yoneda.obj G).map f.op) by
      exact @isIso_of_reflects_iso _ _ _ _ _ _ _ (yoneda.obj G) _ h
theorem isCodetector_iff_reflectsIsomorphisms_yoneda_obj (G : C) :
    IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G) := by
  refine' ⟨fun hG => ⟨fun f hf => _⟩, fun h => (isCodetector_def _).2 fun X Y f hf => _⟩
  · refine' (isIso_unop_iff _).1 (hG.def _ _)
    rwa [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
  · rw [← isIso_op_iff]
    suffices IsIso ((yoneda.obj G).map f.op) by
      

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
h : ReflectsIsomorphisms (yoneda.obj G)
X Y : C
f : X ⟶ Y
hf : ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
this : IsIso ((yoneda.obj G).map f.op)
⊢ IsIso f.op

Next tactic:
exact @isIso_of_reflects_iso _ _ _ _ _ _ _ (yoneda.obj G) _ h
theorem isCodetector_iff_reflectsIsomorphisms_yoneda_obj (G : C) :
    IsCodetector G ↔ ReflectsIsomorphisms (yoneda.obj G) := by
  refine' ⟨fun hG => ⟨fun f hf => _⟩, fun h => (isCodetector_def _).2 fun X Y f hf => _⟩
  · refine' (isIso_unop_iff _).1 (hG.def _ _)
    rwa [isIso_iff_bijective, Function.bijective_iff_existsUnique] at hf
  · rw [← isIso_op_iff]
    suffices IsIso ((yoneda.obj G).map f.op) by
      exact @isIso_of_reflects_iso _ _ _ _ _ _ _ (yoneda.obj G) _ h
    

Proof state:
case refine'_2
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C
h : ReflectsIsomorphisms (yoneda.obj G)
X Y : C
f : X ⟶ Y
hf : ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
⊢ IsIso ((yoneda.obj G).map f.op)

Next tactic:
rwa [isIso_iff_bijective, Function.bijective_iff_existsUnique]
/-- A skyscraper presheaf is a presheaf supported at a single point: if `p₀ ∈ X` is a specified
point, then the skyscraper presheaf `𝓕` with value `A` is defined by `U ↦ A` if `p₀ ∈ U` and
`U ↦ *` if `p₀ ∉ A` where `*` is some terminal object.
-/
@[simps]
def skyscraperPresheaf : Presheaf C X where
  obj U := if p₀ ∈ unop U then A else terminal C
  map {U V} i :=
    if h : p₀ ∈ unop V then eqToHom <| by 

Proof state:
X : TopCat
p₀ : ↑X
inst✝² : (U : Opens ↑X) → Decidable (p₀ ∈ U)
C : Type v
inst✝¹ : Category.{w, v} C
inst✝ : HasTerminal C
A : C
U V : (Opens ↑X)ᵒᵖ
i : U ⟶ V
h : p₀ ∈ V.unop
⊢ (fun U => if p₀ ∈ U.unop then A else ⊤_ C) U = (fun U => if p₀ ∈ U.unop then A else ⊤_ C) V

Next tactic:
dsimp
/-- A skyscraper presheaf is a presheaf supported at a single point: if `p₀ ∈ X` is a specified
point, then the skyscraper presheaf `𝓕` with value `A` is defined by `U ↦ A` if `p₀ ∈ U` and
`U ↦ *` if `p₀ ∉ A` where `*` is some terminal object.
-/
@[simps]
def skyscraperPresheaf : Presheaf C X where
  obj U := if p₀ ∈ unop U then A else terminal C
  map {U V} i :=
    if h : p₀ ∈ unop V then eqToHom <| by dsimp; 

Proof state:
X : TopCat
p₀ : ↑X
inst✝² : (U : Opens ↑X) → Decidable (p₀ ∈ U)
C : Type v
inst✝¹ : Category.{w, v} C
inst✝ : HasTerminal C
A : C
U V : (Opens ↑X)ᵒᵖ
i : U ⟶ V
h : p₀ ∈ V.unop
⊢ (if p₀ ∈ U.unop then A else ⊤_ C) = if p₀ ∈ V.unop then A else ⊤_ C

Next tactic:
erw [if_pos h, if_pos (leOfHom i.unop h)]