-- Mathlib/CategoryTheory/Generator/Basic.lean
theorem isCodetecting_op_iff (𝒢 : Set C) : IsCodetecting 𝒢.op ↔ IsDetecting 𝒢

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
⊢ IsCodetecting 𝒢.op ↔ IsDetecting 𝒢

Tactic:
refine ⟨fun h𝒢 X Y f hf => ?_, fun h𝒢 X Y f hf => ?_⟩

Result:
case refine_1
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsCodetecting 𝒢.op
X Y : C
f : X ⟶ Y
hf : ∀ G ∈ 𝒢, ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
⊢ IsIso f

case refine_2
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
⊢ IsIso f

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
G : C
hG : G ∈ 𝒢
h : G ⟶ unop X
t : Y ⟶ op G
ht : f ≫ t = h.op
ht' : ∀ (y : Y ⟶ op G), (fun h' => f ≫ h' = h.op) y → y = t
y : G ⟶ unop Y
hy : (fun h' => h' ≫ f.unop = h) y
⊢ (f ≫ y.op).unop = h.op.unop

Tactic:
simpa only using hy

Result:
no goals

Proof state:
case refine_2.intro.intro
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
G : C
hG : G ∈ 𝒢
h : G ⟶ unop X
t : Y ⟶ op G
ht : f ≫ t = h.op
ht' : ∀ (y : Y ⟶ op G), (fun h' => f ≫ h' = h.op) y → y = t
⊢ ∃! h', h' ≫ f.unop = h

Tactic:
refine ⟨t.unop, Quiver.Hom.op_inj ht, fun y hy => Quiver.Hom.op_inj (ht' _ ?_)⟩

Result:
case refine_2.intro.intro
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
G : C
hG : G ∈ 𝒢
h : G ⟶ unop X
t : Y ⟶ op G
ht : f ≫ t = h.op
ht' : ∀ (y : Y ⟶ op G), (fun h' => f ≫ h' = h.op) y → y = t
y : G ⟶ unop Y
hy : (fun h' => h' ≫ f.unop = h) y
⊢ (fun h' => f ≫ h' = h.op) y.op

Proof state:
case refine_2.intro.intro
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
G : C
hG : G ∈ 𝒢
h : G ⟶ unop X
t : Y ⟶ op G
ht : f ≫ t = h.op
ht' : ∀ (y : Y ⟶ op G), (fun h' => f ≫ h' = h.op) y → y = t
y : G ⟶ unop Y
hy : (fun h' => h' ≫ f.unop = h) y
⊢ (fun h' => f ≫ h' = h.op) y.op

Tactic:
exact Quiver.Hom.unop_inj (by simpa only using hy)

Result:
no goals

Proof state:
case refine_1.intro.intro
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsCodetecting 𝒢.op
X Y : C
f : X ⟶ Y
hf : ∀ G ∈ 𝒢, ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
G : Cᵒᵖ
hG : G ∈ 𝒢.op
h : op Y ⟶ G
t : unop G ⟶ X
ht : t ≫ f = h.unop
ht' : ∀ (y : unop G ⟶ X), (fun h' => h' ≫ f = h.unop) y → y = t
⊢ ∃! h', f.op ≫ h' = h

Tactic:
exact
  ⟨t.op, Quiver.Hom.unop_inj ht, fun y hy => Quiver.Hom.unop_inj (ht' _ (Quiver.Hom.op_inj hy))⟩

Result:
no goals

Proof state:
case refine_2
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
⊢ IsIso f

Tactic:
refine (isIso_unop_iff _).1 (h𝒢 _ fun G hG h => ?_)

Result:
case refine_2
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
G : C
hG : G ∈ 𝒢
h : G ⟶ unop X
⊢ ∃! h', h' ≫ f.unop = h

Proof state:
case refine_1
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsCodetecting 𝒢.op
X Y : C
f : X ⟶ Y
hf : ∀ G ∈ 𝒢, ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
G : Cᵒᵖ
hG : G ∈ 𝒢.op
h : op Y ⟶ G
⊢ ∃! h', f.op ≫ h' = h

Tactic:
obtain ⟨t, ht, ht'⟩ := hf (unop G) (Set.mem_op.1 hG) h.unop

Result:
case refine_1.intro.intro
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsCodetecting 𝒢.op
X Y : C
f : X ⟶ Y
hf : ∀ G ∈ 𝒢, ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
G : Cᵒᵖ
hG : G ∈ 𝒢.op
h : op Y ⟶ G
t : unop G ⟶ X
ht : t ≫ f = h.unop
ht' : ∀ (y : unop G ⟶ X), (fun h' => h' ≫ f = h.unop) y → y = t
⊢ ∃! h', f.op ≫ h' = h

Proof state:
case refine_2
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
G : C
hG : G ∈ 𝒢
h : G ⟶ unop X
⊢ ∃! h', h' ≫ f.unop = h

Tactic:
obtain ⟨t, ht, ht'⟩ := hf (op G) (Set.op_mem_op.2 hG) h.op

Result:
case refine_2.intro.intro
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsDetecting 𝒢
X Y : Cᵒᵖ
f : X ⟶ Y
hf : ∀ G ∈ 𝒢.op, ∀ (h : X ⟶ G), ∃! h', f ≫ h' = h
G : C
hG : G ∈ 𝒢
h : G ⟶ unop X
t : Y ⟶ op G
ht : f ≫ t = h.op
ht' : ∀ (y : Y ⟶ op G), (fun h' => f ≫ h' = h.op) y → y = t
⊢ ∃! h', h' ≫ f.unop = h

Proof state:
case refine_1
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsCodetecting 𝒢.op
X Y : C
f : X ⟶ Y
hf : ∀ G ∈ 𝒢, ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
⊢ IsIso f

Tactic:
refine (isIso_op_iff _).1 (h𝒢 _ fun G hG h => ?_)

Result:
case refine_1
C : Type u₁
inst✝ : Category.{v₁, u₁} C
𝒢 : Set C
h𝒢 : IsCodetecting 𝒢.op
X Y : C
f : X ⟶ Y
hf : ∀ G ∈ 𝒢, ∀ (h : G ⟶ Y), ∃! h', h' ≫ f = h
G : Cᵒᵖ
hG : G ∈ 𝒢.op
h : op Y ⟶ G
⊢ ∃! h', f.op ≫ h' = h