l3lab/ntp-mathlib huggingface dataset:
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Over.homMk (inv ((forget X).map f))
      ((asIso ((forget X).map f)).inv_comp_eq.2 (Over.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (ext; 

Proof state:
case refine_1.h
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Over X
f : Y ⟶ Z
t : IsIso f.left
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ (f ≫ g).left = (𝟙 Y).left
case refine_2
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Over X
f : Y ⟶ Z
t : IsIso f.left
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ g ≫ f = 𝟙 Z

Next tactic:
simp
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Over.homMk (inv ((forget X).map f))
      ((asIso ((forget X).map f)).inv_comp_eq.2 (Over.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (

Proof state:
case refine_2
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Over X
f : Y ⟶ Z
t : IsIso f.left
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ g ≫ f = 𝟙 Z

Next tactic:
ext
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Over.homMk (inv ((forget X).map f))
      ((asIso ((forget X).map f)).inv_comp_eq.2 (Over.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (ext; 

Proof state:
case refine_2.h
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Over X
f : Y ⟶ Z
t : IsIso f.left
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ (g ≫ f).left = (𝟙 Z).left

Next tactic:
simp
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Over.homMk (inv ((forget X).map f))
      ((asIso ((forget X).map f)).inv_comp_eq.2 (Over.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (

Proof state:

Next tactic:
ext
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
⊢ Mono k.left

Next tactic:
refine' ⟨fun { Y : T } l m a => _⟩
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
⊢ l = m

Next tactic:
let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        dsimp; rw [← Over.w k, ← Category.assoc, congrArg (· ≫ g.hom) a, Category.assoc])
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
⊢ l ≫ f.hom = (mk (m ≫ f.hom)).hom

Next tactic:
dsimp
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        dsimp; 

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
⊢ l ≫ f.hom = m ≫ f.hom

Next tactic:
rw [← Over.w k, ← Category.assoc, congrArg (· ≫ g.hom) a, Category.assoc]
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        dsimp; rw [← Over.w k, ← Category.assoc, congrArg (· ≫ g.hom) a, Category.assoc])
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
l' : mk (m ≫ f.hom) ⟶ f := homMk l
⊢ l = m

Next tactic:
suffices l' = (homMk m : mk (m ≫ f.hom) ⟶ f) by apply congrArg CommaMorphism.left this
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        dsimp; rw [← Over.w k, ← Category.assoc, congrArg (· ≫ g.hom) a, Category.assoc])
  suffices l' = (homMk m : mk (m ≫ f.hom) ⟶ f) by 

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
l' : mk (m ≫ f.hom) ⟶ f := homMk l
this : l' = homMk m
⊢ l = m

Next tactic:
apply congrArg CommaMorphism.left this
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        dsimp; rw [← Over.w k, ← Category.assoc, congrArg (· ≫ g.hom) a, Category.assoc])
  suffices l' = (homMk m : mk (m ≫ f.hom) ⟶ f) by apply congrArg CommaMorphism.left this
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
l' : mk (m ≫ f.hom) ⟶ f := homMk l
⊢ l' = homMk m

Next tactic:
rw [← cancel_mono k]
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        dsimp; rw [← Over.w k, ← Category.assoc, congrArg (· ≫ g.hom) a, Category.assoc])
  suffices l' = (homMk m : mk (m ≫ f.hom) ⟶ f) by apply congrArg CommaMorphism.left this
  rw [← cancel_mono k]
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
l' : mk (m ≫ f.hom) ⟶ f := homMk l
⊢ l' ≫ k = homMk m ≫ k

Next tactic:
ext
/--
If `k` is a monomorphism, then `k.left` is a monomorphism. In other words, `Over.forget X` preserves
monomorphisms.
The converse of `CategoryTheory.Over.mono_of_mono_left`.
-/
instance mono_left_of_mono {f g : Over X} (k : f ⟶ g) [Mono k] : Mono k.left := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : mk (m ≫ f.hom) ⟶ f := homMk l (by
        dsimp; rw [← Over.w k, ← Category.assoc, congrArg (· ≫ g.hom) a, Category.assoc])
  suffices l' = (homMk m : mk (m ≫ f.hom) ⟶ f) by apply congrArg CommaMorphism.left this
  rw [← cancel_mono k]
  ext
  

Proof state:
case h
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Over X
k : f ⟶ g
inst✝ : Mono k
Y : T
l m : Y ⟶ f.left
a : l ≫ k.left = m ≫ k.left
l' : mk (m ≫ f.hom) ⟶ f := homMk l
⊢ (l' ≫ k).left = (homMk m ≫ k).left

Next tactic:
apply a
/-- Given f : Y ⟶ X, this is the obvious functor from (T/X)/f to T/Y -/
@[simps]
def iteratedSliceForward : Over f ⥤ Over f.left
    where
  obj α := Over.mk α.hom.left
  map κ := Over.homMk κ.left.left (by 

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
f : Over X
X✝ Y✝ : Over f
κ : X✝ ⟶ Y✝
⊢ κ.left.left ≫ ((fun α => mk α.hom.left) Y✝).hom = ((fun α => mk α.hom.left) X✝).hom

Next tactic:
dsimp
/-- Given f : Y ⟶ X, this is the obvious functor from (T/X)/f to T/Y -/
@[simps]
def iteratedSliceForward : Over f ⥤ Over f.left
    where
  obj α := Over.mk α.hom.left
  map κ := Over.homMk κ.left.left (by dsimp; 

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
f : Over X
X✝ Y✝ : Over f
κ : X✝ ⟶ Y✝
⊢ κ.left.left ≫ Y✝.hom.left = X✝.hom.left

Next tactic:
rw [← Over.w κ]
/-- Given f : Y ⟶ X, this is the obvious functor from (T/X)/f to T/Y -/
@[simps]
def iteratedSliceForward : Over f ⥤ Over f.left
    where
  obj α := Over.mk α.hom.left
  map κ := Over.homMk κ.left.left (by dsimp; rw [← Over.w κ]; 

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
f : Over X
X✝ Y✝ : Over f
κ : X✝ ⟶ Y✝
⊢ κ.left.left ≫ Y✝.hom.left = (κ.left ≫ Y✝.hom).left

Next tactic:
rfl
/-- A functor `F : T ⥤ D` induces a functor `Over X ⥤ Over (F.obj X)` in the obvious way. -/
@[simps]
def post (F : T ⥤ D) : Over X ⥤ Over (F.obj X)
    where
  obj Y := mk <| F.map Y.hom
  map f := Over.homMk (F.map f.left)
    (by 

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : T ⥤ D
X✝ Y✝ : Over X
f : X✝ ⟶ Y✝
⊢ F.map f.left ≫ ((fun Y => mk (F.map Y.hom)) Y✝).hom = ((fun Y => mk (F.map Y.hom)) X✝).hom

Next tactic:
simp only [Functor.id_obj, mk_left, Functor.const_obj_obj, mk_hom, ← F.map_comp, w]
@[ext]
theorem UnderMorphism.ext {X : T} {U V : Under X} {f g : U ⟶ V} (h : f.right = g.right) :
    f = g := by
  

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X✝ X : T
U V : Under X
f g : U ⟶ V
h : f.right = g.right
⊢ f = g

Next tactic:
let ⟨_,b,_⟩ := f
@[ext]
theorem UnderMorphism.ext {X : T} {U V : Under X} {f g : U ⟶ V} (h : f.right = g.right) :
    f = g := by
  let ⟨_,b,_⟩ := f; 

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X✝ X : T
U V : Under X
f g : U ⟶ V
left✝ : U.left ⟶ V.left
b : U.right ⟶ V.right
w✝ : (Functor.fromPUnit X).map left✝ ≫ V.hom = U.hom ≫ (𝟭 T).map b
h : (CommaMorphism.mk left✝ b).right = g.right
⊢ CommaMorphism.mk left✝ b = g

Next tactic:
let ⟨_,e,_⟩ := g
@[ext]
theorem UnderMorphism.ext {X : T} {U V : Under X} {f g : U ⟶ V} (h : f.right = g.right) :
    f = g := by
  let ⟨_,b,_⟩ := f; let ⟨_,e,_⟩ := g
  

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X✝ X : T
U V : Under X
f g : U ⟶ V
left✝¹ : U.left ⟶ V.left
b : U.right ⟶ V.right
w✝¹ : (Functor.fromPUnit X).map left✝¹ ≫ V.hom = U.hom ≫ (𝟭 T).map b
left✝ : U.left ⟶ V.left
e : U.right ⟶ V.right
w✝ : (Functor.fromPUnit X).map left✝ ≫ V.hom = U.hom ≫ (𝟭 T).map e
h : (CommaMorphism.mk left✝¹ b).right = (CommaMorphism.mk left✝ e).right
⊢ CommaMorphism.mk left✝¹ b = CommaMorphism.mk left✝ e

Next tactic:
congr
@[ext]
theorem UnderMorphism.ext {X : T} {U V : Under X} {f g : U ⟶ V} (h : f.right = g.right) :
    f = g := by
  let ⟨_,b,_⟩ := f; let ⟨_,e,_⟩ := g
  congr; 

Proof state:
case e_left
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X✝ X : T
U V : Under X
f g : U ⟶ V
left✝¹ : U.left ⟶ V.left
b : U.right ⟶ V.right
w✝¹ : (Functor.fromPUnit X).map left✝¹ ≫ V.hom = U.hom ≫ (𝟭 T).map b
left✝ : U.left ⟶ V.left
e : U.right ⟶ V.right
w✝ : (Functor.fromPUnit X).map left✝ ≫ V.hom = U.hom ≫ (𝟭 T).map e
h : (CommaMorphism.mk left✝¹ b).right = (CommaMorphism.mk left✝ e).right
⊢ left✝¹ = left✝

Next tactic:
simp only [eq_iff_true_of_subsingleton]
theorem under_left (U : Under X) : U.left = ⟨⟨⟩⟩ := by 

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
U : Under X
⊢ U.left = { as := PUnit.unit }

Next tactic:
simp only
@[reassoc (attr := simp)]
theorem w {A B : Under X} (f : A ⟶ B) : A.hom ≫ f.right = B.hom := by 

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
A B : Under X
f : A ⟶ B
⊢ A.hom ≫ f.right = B.hom

Next tactic:
have := f.w
@[reassoc (attr := simp)]
theorem w {A B : Under X} (f : A ⟶ B) : A.hom ≫ f.right = B.hom := by have := f.w; 

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
A B : Under X
f : A ⟶ B
this : (Functor.fromPUnit X).map f.left ≫ B.hom = A.hom ≫ (𝟭 T).map f.right
⊢ A.hom ≫ f.right = B.hom

Next tactic:
aesop_cat
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso ((forget X).map f)
⊢ IsIso f

Next tactic:
let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso ((forget X).map f)
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ IsIso f

Next tactic:
dsimp [forget] at t
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    dsimp [forget] at t
    

Proof state:
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ IsIso f

Next tactic:
refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    

Proof state:
case refine_1
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ f ≫ g = 𝟙 Y
case refine_2
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ g ≫ f = 𝟙 Z

Next tactic:
repeat (ext; simp)
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (

Proof state:
case refine_1
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ f ≫ g = 𝟙 Y
case refine_2
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ g ≫ f = 𝟙 Z

Next tactic:
ext
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (ext; 

Proof state:
case refine_1.h
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ (f ≫ g).right = (𝟙 Y).right
case refine_2
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ g ≫ f = 𝟙 Z

Next tactic:
simp
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (

Proof state:
case refine_2
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ g ≫ f = 𝟙 Z

Next tactic:
ext
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (ext; 

Proof state:
case refine_2.h
T : Type u₁
inst✝ : Category.{v₁, u₁} T
X : T
Y Z : Under X
f : Y ⟶ Z
t : IsIso f.right
g : Z ⟶ Y := homMk (inv ((forget X).map f))
⊢ (g ≫ f).right = (𝟙 Z).right

Next tactic:
simp
instance forget_reflects_iso : ReflectsIsomorphisms (forget X) where
  reflects {Y Z} f t := by
    let g : Z ⟶ Y := Under.homMk (inv ((Under.forget X).map f))
      ((IsIso.comp_inv_eq _).2 (Under.w f).symm)
    dsimp [forget] at t
    refine ⟨⟨g, ⟨?_,?_⟩⟩⟩
    repeat (

Proof state:

Next tactic:
ext
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
⊢ Epi k.right

Next tactic:
refine' ⟨fun { Y : T } l m a => _⟩
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
⊢ l = m

Next tactic:
let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    dsimp; rw [← Under.w k, Category.assoc, a, Category.assoc])
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
⊢ g.hom ≫ l = (mk (g.hom ≫ m)).hom

Next tactic:
dsimp
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    dsimp; 

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
⊢ g.hom ≫ l = g.hom ≫ m

Next tactic:
rw [← Under.w k, Category.assoc, a, Category.assoc]
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    dsimp; rw [← Under.w k, Category.assoc, a, Category.assoc])
  -- Porting note: add type ascription here to `homMk m`
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
l' : g ⟶ mk (g.hom ≫ m) := homMk l
⊢ l = m

Next tactic:
suffices l' = (homMk m : g ⟶ mk (g.hom ≫ m)) by apply congrArg CommaMorphism.right this
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    dsimp; rw [← Under.w k, Category.assoc, a, Category.assoc])
  -- Porting note: add type ascription here to `homMk m`
  suffices l' = (homMk m : g ⟶ mk (g.hom ≫ m)) by 

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
l' : g ⟶ mk (g.hom ≫ m) := homMk l
this : l' = homMk m
⊢ l = m

Next tactic:
apply congrArg CommaMorphism.right this
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    dsimp; rw [← Under.w k, Category.assoc, a, Category.assoc])
  -- Porting note: add type ascription here to `homMk m`
  suffices l' = (homMk m : g ⟶ mk (g.hom ≫ m)) by apply congrArg CommaMorphism.right this
  

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
l' : g ⟶ mk (g.hom ≫ m) := homMk l
⊢ l' = homMk m

Next tactic:
rw [← cancel_epi k]
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    dsimp; rw [← Under.w k, Category.assoc, a, Category.assoc])
  -- Porting note: add type ascription here to `homMk m`
  suffices l' = (homMk m : g ⟶ mk (g.hom ≫ m)) by apply congrArg CommaMorphism.right this
  rw [← cancel_epi k]; 

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
l' : g ⟶ mk (g.hom ≫ m) := homMk l
⊢ k ≫ l' = k ≫ homMk m

Next tactic:
ext
/--
If `k` is an epimorphism, then `k.right` is an epimorphism. In other words, `Under.forget X`
preserves epimorphisms.
The converse of `CategoryTheory.under.epi_of_epi_right`.
-/
instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := by
  refine' ⟨fun { Y : T } l m a => _⟩
  let l' : g ⟶ mk (g.hom ≫ m) := homMk l (by
    dsimp; rw [← Under.w k, Category.assoc, a, Category.assoc])
  -- Porting note: add type ascription here to `homMk m`
  suffices l' = (homMk m : g ⟶ mk (g.hom ≫ m)) by apply congrArg CommaMorphism.right this
  rw [← cancel_epi k]; ext; 

Proof state:
case h
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X : T
f g : Under X
k : f ⟶ g
inst✝ : Epi k
Y : T
l m : g.right ⟶ Y
a : k.right ≫ l = k.right ≫ m
l' : g ⟶ mk (g.hom ≫ m) := homMk l
⊢ (k ≫ l').right = (k ≫ homMk m).right

Next tactic:
apply a
/-- A functor `F : T ⥤ D` induces a functor `Under X ⥤ Under (F.obj X)` in the obvious way. -/
@[simps]
def post {X : T} (F : T ⥤ D) : Under X ⥤ Under (F.obj X) where
  obj Y := mk <| F.map Y.hom
  map f := Under.homMk (F.map f.right)
    (by 

Proof state:
T : Type u₁
inst✝¹ : Category.{v₁, u₁} T
X✝¹ : T
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : T
F : T ⥤ D
X✝ Y✝ : Under X
f : X✝ ⟶ Y✝
⊢ ((fun Y => mk (F.map Y.hom)) X✝).hom ≫ F.map f.right = ((fun Y => mk (F.map Y.hom)) Y✝).hom

Next tactic:
simp only [Functor.id_obj, Functor.const_obj_obj, mk_right, mk_hom, ← F.map_comp, w]