l3lab/ntp-mathlib huggingface dataset:
/-- The identity structured arrow is initial. -/
def mkIdInitial [Full T] [Faithful T] : IsInitial (mk (𝟙 (T.obj Y))) where
  desc c := homMk (T.preimage c.pt.hom)
  uniq c m _ := by
    apply CommaMorphism.ext
    · aesop_cat
    · apply T.map_injective
      

Proof state:
case right.a
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
inst✝¹ : Full T
inst✝ : Faithful T
c : Cocone (Functor.empty (StructuredArrow (T.obj Y) T))
m : (asEmptyCocone (mk (𝟙 (T.obj Y)))).pt ⟶ c.pt
x✝ : ∀ (j : Discrete PEmpty.{1}), (asEmptyCocone (mk (𝟙 (T.obj Y)))).ι.app j ≫ m = c.ι.app j
⊢ T.map m.right = T.map ((fun c => homMk (T.preimage c.pt.hom)) c).right

Next tactic:
simpa only [homMk_right, T.image_preimage, ← w m] using (Category.id_comp _).symm
/-- The functor `(S, F) ⥤ (G(S), F ⋙ G)`. -/
@[simps]
def post (S : C) (F : B ⥤ C) (G : C ⥤ D) : StructuredArrow S F ⥤ StructuredArrow (G.obj S) (F ⋙ G)
    where
  obj X := StructuredArrow.mk (G.map X.hom)
  map f := StructuredArrow.homMk f.right (by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S✝ S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝¹ : Category.{v₃, u₃} A
B : Type u₄
inst✝ : Category.{v₄, u₄} B
S : C
F : B ⥤ C
G : C ⥤ D
X✝ Y✝ : StructuredArrow S F
f : X✝ ⟶ Y✝
⊢ ((fun X => mk (G.map X.hom)) X✝).hom ≫ (F ⋙ G).map f.right = ((fun X => mk (G.map X.hom)) Y✝).hom

Next tactic:
simp [Functor.comp_map, ← G.map_comp, ← f.w]
instance (S : C) (F : B ⥤ C) (G : C ⥤ D) : Faithful (post S F G) where
  map_injective {_ _} _ _ h := by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S✝ S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝¹ : Category.{v₃, u₃} A
B : Type u₄
inst✝ : Category.{v₄, u₄} B
S : C
F : B ⥤ C
G : C ⥤ D
x✝³ x✝² : StructuredArrow S F
x✝¹ x✝ : x✝³ ⟶ x✝²
h : (post S F G).map x✝¹ = (post S F G).map x✝
⊢ x✝¹ = x✝

Next tactic:
simpa [ext_iff] using h
instance (S : C) (F : B ⥤ C) (G : C ⥤ D) [Faithful G] : Full (post S F G) where
  preimage {_ _} f := homMk f.right (G.map_injective (by 

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
S✝ S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
B : Type u₄
inst✝¹ : Category.{v₄, u₄} B
S : C
F : B ⥤ C
G : C ⥤ D
inst✝ : Faithful G
x✝¹ x✝ : StructuredArrow S F
f : (post S F G).obj x✝¹ ⟶ (post S F G).obj x✝
⊢ G.map (x✝¹.hom ≫ F.map f.right) = G.map x✝.hom

Next tactic:
simpa using f.w.symm
instance (S : C) (F : B ⥤ C) (G : C ⥤ D) [Full G] : EssSurj (post S F G) where
  mem_essImage h := ⟨mk (G.preimage h.hom), ⟨isoMk (Iso.refl _) (by 

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
S✝ S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
B : Type u₄
inst✝¹ : Category.{v₄, u₄} B
S : C
F : B ⥤ C
G : C ⥤ D
inst✝ : Full G
h : StructuredArrow (G.obj S) (F ⋙ G)
⊢ ((post S F G).obj (mk (G.preimage h.hom))).hom ≫
      (F ⋙ G).map (Iso.refl ((post S F G).obj (mk (G.preimage h.hom))).right).hom =
    h.hom

Next tactic:
simp
instance small_proj_preimage_of_locallySmall {𝒢 : Set C} [Small.{v₁} 𝒢] [LocallySmall.{v₁} D] :
    Small.{v₁} ((proj S T).obj ⁻¹' 𝒢) := by
  

Proof state:
C : Type u₁
inst✝⁵ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝³ : Category.{v₃, u₃} A
B : Type u₄
inst✝² : Category.{v₄, u₄} B
𝒢 : Set C
inst✝¹ : Small.{v₁, u₁} ↑𝒢
inst✝ : LocallySmall.{v₁, v₂, u₂} D
⊢ Small.{v₁, max u₁ v₂} ↑((proj S T).toPrefunctor.obj ⁻¹' 𝒢)

Next tactic:
suffices (proj S T).obj ⁻¹' 𝒢 = Set.range fun f : ΣG : 𝒢, S ⟶ T.obj G => mk f.2 by
    rw [this]
    infer_instance
instance small_proj_preimage_of_locallySmall {𝒢 : Set C} [Small.{v₁} 𝒢] [LocallySmall.{v₁} D] :
    Small.{v₁} ((proj S T).obj ⁻¹' 𝒢) := by
  suffices (proj S T).obj ⁻¹' 𝒢 = Set.range fun f : ΣG : 𝒢, S ⟶ T.obj G => mk f.2 by
    

Proof state:
C : Type u₁
inst✝⁵ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝³ : Category.{v₃, u₃} A
B : Type u₄
inst✝² : Category.{v₄, u₄} B
𝒢 : Set C
inst✝¹ : Small.{v₁, u₁} ↑𝒢
inst✝ : LocallySmall.{v₁, v₂, u₂} D
this : (proj S T).toPrefunctor.obj ⁻¹' 𝒢 = Set.range fun f => mk f.snd
⊢ Small.{v₁, max u₁ v₂} ↑((proj S T).toPrefunctor.obj ⁻¹' 𝒢)

Next tactic:
rw [this]
instance small_proj_preimage_of_locallySmall {𝒢 : Set C} [Small.{v₁} 𝒢] [LocallySmall.{v₁} D] :
    Small.{v₁} ((proj S T).obj ⁻¹' 𝒢) := by
  suffices (proj S T).obj ⁻¹' 𝒢 = Set.range fun f : ΣG : 𝒢, S ⟶ T.obj G => mk f.2 by
    rw [this]
    

Proof state:
C : Type u₁
inst✝⁵ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝³ : Category.{v₃, u₃} A
B : Type u₄
inst✝² : Category.{v₄, u₄} B
𝒢 : Set C
inst✝¹ : Small.{v₁, u₁} ↑𝒢
inst✝ : LocallySmall.{v₁, v₂, u₂} D
this : (proj S T).toPrefunctor.obj ⁻¹' 𝒢 = Set.range fun f => mk f.snd
⊢ Small.{v₁, max u₁ v₂} ↑(Set.range fun f => mk f.snd)

Next tactic:
infer_instance
instance small_proj_preimage_of_locallySmall {𝒢 : Set C} [Small.{v₁} 𝒢] [LocallySmall.{v₁} D] :
    Small.{v₁} ((proj S T).obj ⁻¹' 𝒢) := by
  suffices (proj S T).obj ⁻¹' 𝒢 = Set.range fun f : ΣG : 𝒢, S ⟶ T.obj G => mk f.2 by
    rw [this]
    infer_instance
  

Proof state:
C : Type u₁
inst✝⁵ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝³ : Category.{v₃, u₃} A
B : Type u₄
inst✝² : Category.{v₄, u₄} B
𝒢 : Set C
inst✝¹ : Small.{v₁, u₁} ↑𝒢
inst✝ : LocallySmall.{v₁, v₂, u₂} D
⊢ (proj S T).toPrefunctor.obj ⁻¹' 𝒢 = Set.range fun f => mk f.snd

Next tactic:
exact Set.ext fun X => ⟨fun h => ⟨⟨⟨_, h⟩, X.hom⟩, (eq_mk _).symm⟩, by aesop_cat⟩
instance small_proj_preimage_of_locallySmall {𝒢 : Set C} [Small.{v₁} 𝒢] [LocallySmall.{v₁} D] :
    Small.{v₁} ((proj S T).obj ⁻¹' 𝒢) := by
  suffices (proj S T).obj ⁻¹' 𝒢 = Set.range fun f : ΣG : 𝒢, S ⟶ T.obj G => mk f.2 by
    rw [this]
    infer_instance
  exact Set.ext fun X => ⟨fun h => ⟨⟨⟨_, h⟩, X.hom⟩, (eq_mk _).symm⟩, by 

Proof state:
C : Type u₁
inst✝⁵ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁴ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝³ : Category.{v₃, u₃} A
B : Type u₄
inst✝² : Category.{v₄, u₄} B
𝒢 : Set C
inst✝¹ : Small.{v₁, u₁} ↑𝒢
inst✝ : LocallySmall.{v₁, v₂, u₂} D
X : StructuredArrow S T
⊢ (X ∈ Set.range fun f => mk f.snd) → X ∈ (proj S T).toPrefunctor.obj ⁻¹' 𝒢

Next tactic:
aesop_cat
/-- Two morphisms out of a universal `T`-structured arrow are equal if their image under `T` are
equal after precomposing the universal arrow. -/
theorem hom_ext (h : IsUniversal f) {c : C} {η η' : f.right ⟶ c}
    (w : f.hom ≫ T.map η = f.hom ≫ T.map η') : η = η' := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝¹ : Category.{v₃, u₃} A
B : Type u₄
inst✝ : Category.{v₄, u₄} B
f g : StructuredArrow S T
h : IsUniversal f
c : C
η η' : f.right ⟶ c
w : f.hom ≫ T.map η = f.hom ≫ T.map η'
⊢ η = η'

Next tactic:
rw [h.hom_desc η, h.hom_desc η', w]
theorem existsUnique (h : IsUniversal f) (g : StructuredArrow S T) :
    ∃! η : f.right ⟶ g.right, f.hom ≫ T.map η = g.hom :=
  ⟨h.desc g, h.fac g, fun f w ↦ h.hom_ext <| by 

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A : Type u₃
inst✝¹ : Category.{v₃, u₃} A
B : Type u₄
inst✝ : Category.{v₄, u₄} B
f✝ g✝ : StructuredArrow S T
h : IsUniversal f✝
g : StructuredArrow S T
f : f✝.right ⟶ g.right
w : (fun η => f✝.hom ≫ T.map η = g.hom) f
⊢ f✝.hom ≫ T.map f = f✝.hom ≫ T.map (desc h g)

Next tactic:
simp [w]
@[simp]
theorem hom_eq_iff {X Y : CostructuredArrow S T} (f g : X ⟶ Y) : f = g ↔ f.left = g.left :=
  ⟨fun h ↦ by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
X Y : CostructuredArrow S T
f g : X ⟶ Y
h : f = g
⊢ f.left = g.left

Next tactic:
rw [h]
@[reassoc]
theorem w {A B : CostructuredArrow S T} (f : A ⟶ B) : S.map f.left ≫ B.hom = A.hom := by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
A B : CostructuredArrow S T
f : A ⟶ B
⊢ S.map f.left ≫ B.hom = A.hom

Next tactic:
simp
@[simp]
theorem eqToHom_left {X Y : CostructuredArrow S T} (h : X = Y) :
    (eqToHom h).left = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
X Y : CostructuredArrow S T
h : X = Y
⊢ X.left = Y.left

Next tactic:
rw [h]
@[simp]
theorem eqToHom_left {X Y : CostructuredArrow S T} (h : X = Y) :
    (eqToHom h).left = eqToHom (by rw [h]) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
X Y : CostructuredArrow S T
h : X = Y
⊢ (eqToHom h).left = eqToHom (_ : X.left = Y.left)

Next tactic:
subst h
@[simp]
theorem eqToHom_left {X Y : CostructuredArrow S T} (h : X = Y) :
    (eqToHom h).left = eqToHom (by rw [h]) := by
  subst h
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
X : CostructuredArrow S T
⊢ (eqToHom (_ : X = X)).left = eqToHom (_ : X.left = X.left)

Next tactic:
simp only [eqToHom_refl, id_left]
/-- To construct a morphism of costructured arrows,
we need a morphism of the objects underlying the source,
and to check that the triangle commutes.
-/
@[simps!]
def homMk {f f' : CostructuredArrow S T} (g : f.left ⟶ f'.left)
    (w : S.map g ≫ f'.hom = f.hom := by aesop_cat) : f ⟶ f' where
  left := g
  right := eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f f' : CostructuredArrow S T
g : f.left ⟶ f'.left
w : autoParam (S.map g ≫ f'.hom = f.hom) _auto✝
⊢ f.right = f'.right

Next tactic:
ext
/-- To construct a morphism of costructured arrows,
we need a morphism of the objects underlying the source,
and to check that the triangle commutes.
-/
@[simps!]
def homMk {f f' : CostructuredArrow S T} (g : f.left ⟶ f'.left)
    (w : S.map g ≫ f'.hom = f.hom := by aesop_cat) : f ⟶ f' where
  left := g
  right := eqToHom (by ext)
  w := by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f f' : CostructuredArrow S T
g : f.left ⟶ f'.left
w : autoParam (S.map g ≫ f'.hom = f.hom) _auto✝
⊢ S.map g ≫ f'.hom = f.hom ≫ (Functor.fromPUnit T).map (eqToHom (_ : f.right = f'.right))

Next tactic:
simpa [eqToHom_map] using w
/-- Given a costructured arrow `S(Y) ⟶ X`, and an arrow `Y' ⟶ Y'`, we can construct a morphism of
    costructured arrows given by `(S(Y) ⟶ X) ⟶ (S(Y') ⟶ S(Y) ⟶ X)`. -/
@[simps]
def homMk' (f : CostructuredArrow S T) (g : Y' ⟶ f.left) : mk (S.map g ≫ f.hom) ⟶ f where
  left := g
  right := eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
g : Y' ⟶ f.left
⊢ (mk (S.map g ≫ f.hom)).right = f.right

Next tactic:
ext
lemma homMk'_id (f : CostructuredArrow S T) : homMk' f (𝟙 f.left) = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
⊢ mk (S.map (𝟙 f.left) ≫ f.hom) = f

Next tactic:
aesop_cat
lemma homMk'_id (f : CostructuredArrow S T) : homMk' f (𝟙 f.left) = eqToHom (by aesop_cat) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
⊢ homMk' f (𝟙 f.left) = eqToHom (_ : mk (S.map (𝟙 f.left) ≫ f.hom) = f)

Next tactic:
ext
lemma homMk'_id (f : CostructuredArrow S T) : homMk' f (𝟙 f.left) = eqToHom (by aesop_cat) := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
⊢ (homMk' f (𝟙 f.left)).left = (eqToHom (_ : mk (S.map (𝟙 f.left) ≫ f.hom) = f)).left

Next tactic:
simp [eqToHom_left]
lemma homMk'_mk_id (f : S.obj Y ⟶ T) : homMk' (mk f) (𝟙 Y) = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : S.obj Y ⟶ T
⊢ mk (S.map (𝟙 Y) ≫ (mk f).hom) = mk f

Next tactic:
aesop_cat
lemma homMk'_comp (f : CostructuredArrow S T) (g : Y' ⟶ f.left) (g' : Y'' ⟶ Y') :
    homMk' f (g' ≫ g) = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
g : Y' ⟶ f.left
g' : Y'' ⟶ Y'
⊢ mk (S.map (g' ≫ g) ≫ f.hom) = mk (S.map g' ≫ (mk (S.map g ≫ f.hom)).hom)

Next tactic:
simp
lemma homMk'_comp (f : CostructuredArrow S T) (g : Y' ⟶ f.left) (g' : Y'' ⟶ Y') :
    homMk' f (g' ≫ g) = eqToHom (by simp) ≫ homMk' (mk (S.map g ≫ f.hom)) g' ≫ homMk' f g := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
g : Y' ⟶ f.left
g' : Y'' ⟶ Y'
⊢ homMk' f (g' ≫ g) =
    eqToHom (_ : mk (S.map (g' ≫ g) ≫ f.hom) = mk (S.map g' ≫ S.map g ≫ f.hom)) ≫
      homMk' (mk (S.map g ≫ f.hom)) g' ≫ homMk' f g

Next tactic:
ext
lemma homMk'_comp (f : CostructuredArrow S T) (g : Y' ⟶ f.left) (g' : Y'' ⟶ Y') :
    homMk' f (g' ≫ g) = eqToHom (by simp) ≫ homMk' (mk (S.map g ≫ f.hom)) g' ≫ homMk' f g := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
g : Y' ⟶ f.left
g' : Y'' ⟶ Y'
⊢ (homMk' f (g' ≫ g)).left =
    (eqToHom (_ : mk (S.map (g' ≫ g) ≫ f.hom) = mk (S.map g' ≫ S.map g ≫ f.hom)) ≫
        homMk' (mk (S.map g ≫ f.hom)) g' ≫ homMk' f g).left

Next tactic:
simp [eqToHom_left]
lemma homMk'_mk_comp (f : S.obj Y ⟶ T) (g : Y' ⟶ Y) (g' : Y'' ⟶ Y') :
    homMk' (mk f) (g' ≫ g) = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : S.obj Y ⟶ T
g : Y' ⟶ Y
g' : Y'' ⟶ Y'
⊢ mk (S.map (g' ≫ g) ≫ (mk f).hom) = mk (S.map g' ≫ (mk (S.map g ≫ f)).hom)

Next tactic:
simp
/-- To construct an isomorphism of costructured arrows,
we need an isomorphism of the objects underlying the source,
and to check that the triangle commutes.
-/
@[simps!]
def isoMk {f f' : CostructuredArrow S T} (g : f.left ≅ f'.left)
    (w : S.map g.hom ≫ f'.hom = f.hom := by aesop_cat) : f ≅ f' :=
  Comma.isoMk g (eqToIso (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f f' : CostructuredArrow S T
g : f.left ≅ f'.left
w : autoParam (S.map g.hom ≫ f'.hom = f.hom) _auto✝
⊢ f.right = f'.right

Next tactic:
ext
/-- To construct an isomorphism of costructured arrows,
we need an isomorphism of the objects underlying the source,
and to check that the triangle commutes.
-/
@[simps!]
def isoMk {f f' : CostructuredArrow S T} (g : f.left ≅ f'.left)
    (w : S.map g.hom ≫ f'.hom = f.hom := by aesop_cat) : f ≅ f' :=
  Comma.isoMk g (eqToIso (by ext)) (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f f' : CostructuredArrow S T
g : f.left ≅ f'.left
w : autoParam (S.map g.hom ≫ f'.hom = f.hom) _auto✝
⊢ S.map g.hom ≫ f'.hom = f.hom ≫ (Functor.fromPUnit T).map (eqToIso (_ : f.right = f'.right)).hom

Next tactic:
simpa [eqToHom_map] using w
@[simp]
theorem map_id {f : CostructuredArrow S T} : (map (𝟙 T)).obj f = f := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
⊢ (map (𝟙 T)).obj f = f

Next tactic:
rw [eq_mk f]
@[simp]
theorem map_id {f : CostructuredArrow S T} : (map (𝟙 T)).obj f = f := by
  rw [eq_mk f]
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : CostructuredArrow S T
⊢ (map (𝟙 T)).obj (mk f.hom) = mk f.hom

Next tactic:
simp
@[simp]
theorem map_comp {f : T ⟶ T'} {f' : T' ⟶ T''} {h : CostructuredArrow S T} :
    (map (f ≫ f')).obj h = (map f').obj ((map f).obj h) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : T ⟶ T'
f' : T' ⟶ T''
h : CostructuredArrow S T
⊢ (map (f ≫ f')).obj h = (map f').obj ((map f).obj h)

Next tactic:
rw [eq_mk h]
@[simp]
theorem map_comp {f : T ⟶ T'} {f' : T' ⟶ T''} {h : CostructuredArrow S T} :
    (map (f ≫ f')).obj h = (map f').obj ((map f).obj h) := by
  rw [eq_mk h]
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
f : T ⟶ T'
f' : T' ⟶ T''
h : CostructuredArrow S T
⊢ (map (f ≫ f')).obj (mk h.hom) = (map f').obj ((map f).obj (mk h.hom))

Next tactic:
simp
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ S.map (inv ((proj S T).map f)) ≫ Y.hom = Z.hom

Next tactic:
rw [Functor.map_inv, IsIso.inv_comp_eq]
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ Y.hom = S.map ((proj S T).map f) ≫ Z.hom

Next tactic:
simp
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; simp),
      by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ f ≫ homMk (inv ((proj S T).map f)) = 𝟙 Y ∧ homMk (inv ((proj S T).map f)) ≫ f = 𝟙 Z

Next tactic:
constructor
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; simp),
      by constructor <;> 

Proof state:
case left
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ f ≫ homMk (inv ((proj S T).map f)) = 𝟙 Y

Next tactic:
ext
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; simp),
      by constructor <;> 

Proof state:
case right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ homMk (inv ((proj S T).map f)) ≫ f = 𝟙 Z

Next tactic:
ext
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; simp),
      by constructor <;> ext <;> 

Proof state:
case left.h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ (f ≫ homMk (inv ((proj S T).map f))).left = (𝟙 Y).left

Next tactic:
dsimp at t ⊢
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; simp),
      by constructor <;> ext <;> 

Proof state:
case right.h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ (homMk (inv ((proj S T).map f)) ≫ f).left = (𝟙 Z).left

Next tactic:
dsimp at t ⊢
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; simp),
      by constructor <;> ext <;> dsimp at t ⊢ <;> 

Proof state:
case left.h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso f.left
⊢ f.left ≫ inv f.left = 𝟙 Y.left

Next tactic:
simp
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨CostructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.inv_comp_eq]; simp),
      by constructor <;> ext <;> dsimp at t ⊢ <;> 

Proof state:
case right.h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
T T' T'' : D
Y✝ Y' Y'' : C
S S' : C ⥤ D
Y Z : CostructuredArrow S T
f : Y ⟶ Z
t : IsIso f.left
⊢ inv f.left ≫ f.left = 𝟙 Z.left

Next tactic:
simp
/-- The identity costructured arrow is terminal. -/
def mkIdTerminal [Full S] [Faithful S] : IsTerminal (mk (𝟙 (S.obj Y))) where
  lift c := homMk (S.preimage c.pt.hom)
  uniq := by
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
inst✝¹ : Full S
inst✝ : Faithful S
⊢ ∀ (s : Cone (Functor.empty (CostructuredArrow S (S.obj Y)))) (m : s.pt ⟶ (asEmptyCone (mk (𝟙 (S.obj Y)))).pt),
    (∀ (j : Discrete PEmpty.{1}), m ≫ (asEmptyCone (mk (𝟙 (S.obj Y)))).π.app j = s.π.app j) →
      m = (fun c => homMk (S.preimage c.pt.hom)) s

Next tactic:
rintro c m -
/-- The identity costructured arrow is terminal. -/
def mkIdTerminal [Full S] [Faithful S] : IsTerminal (mk (𝟙 (S.obj Y))) where
  lift c := homMk (S.preimage c.pt.hom)
  uniq := by
    rintro c m -
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
inst✝¹ : Full S
inst✝ : Faithful S
c : Cone (Functor.empty (CostructuredArrow S (S.obj Y)))
m : c.pt ⟶ (asEmptyCone (mk (𝟙 (S.obj Y)))).pt
⊢ m = (fun c => homMk (S.preimage c.pt.hom)) c

Next tactic:
ext
/-- The identity costructured arrow is terminal. -/
def mkIdTerminal [Full S] [Faithful S] : IsTerminal (mk (𝟙 (S.obj Y))) where
  lift c := homMk (S.preimage c.pt.hom)
  uniq := by
    rintro c m -
    ext
    

Proof state:
case h
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
T T' T'' : D
Y Y' Y'' : C
S S' : C ⥤ D
inst✝¹ : Full S
inst✝ : Faithful S
c : Cone (Functor.empty (CostructuredArrow S (S.obj Y)))
m : c.pt ⟶ (asEmptyCone (mk (𝟙 (S.obj Y)))).pt
⊢ m.left = ((fun c => homMk (S.preimage c.pt.hom)) c).left

Next tactic:
apply S.map_injective