Theorem: CategoryTheory.extensiveTopology.surjective_of_isLocallySurjective_sheafOfTypes
File: Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean

tactic: intro x
state_before: C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
h : Presheaf.IsLocallySurjective (extensiveTopology C) f
X : C
⊢ Function.Surjective (f.app { unop := X })
state_after: C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
h : Presheaf.IsLocallySurjective (extensiveTopology C) f
X : C
x : G.obj { unop := X }
⊢ ∃ a, f.app { unop := X } a = x

tactic: replace h := h.1 x
state_before: C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
h : Presheaf.IsLocallySurjective (extensiveTopology C) f
X : C
x : G.obj { unop := X }
⊢ ∃ a, f.app { unop := X } a = x
state_after: C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
h : Presheaf.imageSieve f x ∈ (extensiveTopology C).sieves X
⊢ ∃ a, f.app { unop := X } a = x

tactic: rw [mem_sieves_iff_contains_colimit_cofan] at h
state_before: C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
h : Presheaf.imageSieve f x ∈ (extensiveTopology C).sieves X
⊢ ∃ a, f.app { unop := X } a = x
state_after: C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
h :
  ∃ α, ∃ (_ : Finite α), ∃ Y π, Nonempty (IsColimit (Cofan.mk X π)) ∧ ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
⊢ ∃ a, f.app { unop := X } a = x

tactic: obtain ⟨α, _, Y, π, h, h'⟩ := h
state_before: C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
h :
  ∃ α, ∃ (_ : Finite α), ∃ Y π, Nonempty (IsColimit (Cofan.mk X π)) ∧ ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
⊢ ∃ a, f.app { unop := X } a = x
state_after: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
⊢ ∃ a, f.app { unop := X } a = x

tactic: let y : (a : α) → (F.obj ⟨Y a⟩) := fun a ↦ (h' a).choose
state_before: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
⊢ ∃ a, f.app { unop := X } a = x
state_after: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
⊢ ∃ a, f.app { unop := X } a = x

tactic: let _ : Fintype α := Fintype.ofFinite _
state_before: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
⊢ ∃ a, f.app { unop := X } a = x
state_after: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
⊢ ∃ a, f.app { unop := X } a = x

tactic: let ht := (Types.productLimitCone (fun a ↦ F.obj ⟨Y a⟩)).isLimit
state_before: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
⊢ ∃ a, f.app { unop := X } a = x
state_after: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
⊢ ∃ a, f.app { unop := X } a = x

tactic: let ht' := (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse
  (Cocone.op (Cofan.mk X π))).symm h.some.op
state_before: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
⊢ ∃ a, f.app { unop := X } a = x
state_after: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
⊢ ∃ a, f.app { unop := X } a = x

tactic: let i : ((a : α) → (F.obj ⟨Y a⟩)) ≅ (F.obj ⟨X⟩) :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht')
    (Discrete.natIso (fun _ ↦ (Iso.refl (F.obj ⟨_⟩))))
state_before: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
⊢ ∃ a, f.app { unop := X } a = x
state_after: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
⊢ ∃ a, f.app { unop := X } a = x

tactic: refine ⟨i.hom y, ?_⟩
state_before: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
⊢ ∃ a, f.app { unop := X } a = x
state_after: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
⊢ f.app { unop := X } (i.hom y) = x

tactic: apply Concrete.isLimit_ext _ (isLimitOfPreserves G ht')
state_before: case intro.intro.intro.intro.intro
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
⊢ f.app { unop := X } (i.hom y) = x
state_after: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
⊢ ∀ (j : Discrete α),
    ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app j)
        (f.app { unop := X } (i.hom y)) =
      ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app j) x

tactic: intro ⟨a⟩
state_before: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
⊢ ∀ (j : Discrete α),
    ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app j)
        (f.app { unop := X } (i.hom y)) =
      ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app j) x
state_after: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
⊢ ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app { as := a })
      (f.app { unop := X } (i.hom y)) =
    ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app { as := a }) x

tactic: simp only [Functor.comp_obj, Discrete.opposite_inverse_obj, Functor.op_obj, Discrete.functor_obj,
  Functor.mapCone_pt, Cone.whisker_pt, Cocone.op_pt, Cofan.mk_pt, Functor.const_obj_obj,
  Functor.mapCone_π_app, Cone.whisker_π, Cocone.op_π, whiskerLeft_app, NatTrans.op_app,
  Cofan.mk_ι_app]
state_before: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
⊢ ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app { as := a })
      (f.app { unop := X } (i.hom y)) =
    ((G.mapCone (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π)))).π.app { as := a }) x
state_after: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
⊢ (G.map (π a).op) (f.app { unop := X } (i.hom y)) = (G.map (π a).op) x

tactic: have : f.app ⟨Y a⟩ (y a) = G.map (π a).op x := (h' a).choose_spec
state_before: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
⊢ (G.map (π a).op) (f.app { unop := X } (i.hom y)) = (G.map (π a).op) x
state_after: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (G.map (π a).op) (f.app { unop := X } (i.hom y)) = (G.map (π a).op) x

tactic: change _ = G.map (π a).op x
state_before: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (G.map (π a).op) (f.app { unop := X } (i.hom y)) = (G.map (π a).op) x
state_after: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (G.map (π a).op) (f.app { unop := X } (i.hom y)) = G.map (π a).op x

tactic: erw [← this, ← NatTrans.naturality_apply (φ := f)]
state_before: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (G.map (π a).op) (f.app { unop := X } (i.hom y)) = G.map (π a).op x
state_after: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (f.app { unop := Y a }) ((F.map (π a).op) (i.hom y)) = f.app { unop := Y a } (y a)

tactic: apply congrArg
state_before: case intro.intro.intro.intro.intro.a
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (f.app { unop := Y a }) ((F.map (π a).op) (i.hom y)) = f.app { unop := Y a } (y a)
state_after: case intro.intro.intro.intro.intro.a.h
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (F.map (π a).op) (i.hom y) = y a

tactic: change (i.hom ≫ F.map (π a).op) y = _
state_before: case intro.intro.intro.intro.intro.a.h
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (F.map (π a).op) (i.hom y) = y a
state_after: case intro.intro.intro.intro.intro.a.h
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (i.hom ≫ F.map (π a).op) y = y a

tactic: erw [IsLimit.map_π]
state_before: case intro.intro.intro.intro.intro.a.h
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ (i.hom ≫ F.map (π a).op) y = y a
state_after: case intro.intro.intro.intro.intro.a.h
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ ((Types.productLimitCone fun a => F.obj { unop := Y a }).cone.π.app { as := a } ≫
        (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as })).hom.app { as := a })
      y =
    y a

tactic: rfl
state_before: case intro.intro.intro.intro.intro.a.h
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{u_3, u_1} C
inst✝⁴ : Category.{?u.2888, u_2} D
inst✝³ : ConcreteCategory D
inst✝² : FinitaryPreExtensive C
F G : Cᵒᵖ ⥤ Type w
f : F ⟶ G
inst✝¹ : PreservesFiniteProducts F
inst✝ : PreservesFiniteProducts G
X : C
x : G.obj { unop := X }
α : Type
w✝ : Finite α
Y : α → C
π : (a : α) → Y a ⟶ X
h : Nonempty (IsColimit (Cofan.mk X π))
h' : ∀ (a : α), (Presheaf.imageSieve f x).arrows (π a)
y : (a : α) → F.obj { unop := Y a } := fun a => Exists.choose ⋯
x✝ : Fintype α := Fintype.ofFinite α
ht : IsLimit (Types.productLimitCone fun a => F.obj { unop := Y a }).cone :=
  (Types.productLimitCone fun a => F.obj { unop := Y a }).isLimit
ht' : IsLimit (Cone.whisker (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))) :=
  (Functor.Initial.isLimitWhiskerEquiv (Discrete.opposite α).inverse (Cocone.op (Cofan.mk X π))).symm h.some.op
i : ((a : α) → F.obj { unop := Y a }) ≅ F.obj { unop := X } :=
  ht.conePointsIsoOfNatIso (isLimitOfPreserves F ht') (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as }))
a : α
this : f.app { unop := Y a } (y a) = G.map (π a).op x
⊢ ((Types.productLimitCone fun a => F.obj { unop := Y a }).cone.π.app { as := a } ≫
        (Discrete.natIso fun x => Iso.refl (F.obj { unop := Y x.as })).hom.app { as := a })
      y =
    y a
state_after: no goals