Theorem: CategoryTheory.Functor.final_iff_of_isFiltered
File: Mathlib/CategoryTheory/Filtered/Final.lean

tactic: refine ⟨fun hF => ⟨?_, ?_⟩, fun h => final_of_exists_of_isFiltered F h.1 h.2⟩
state_before: C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
⊢ F.Final ↔
    (∀ (d : D), ∃ c, Nonempty (d ⟶ F.obj c)) ∧
      ∀ {d : D} {c : C} (s s' : d ⟶ F.obj c), ∃ c' t, s ≫ F.map t = s' ≫ F.map t
state_after: case refine_1
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
⊢ ∀ (d : D), ∃ c, Nonempty (d ⟶ F.obj c)

case refine_2
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
⊢ ∀ {d : D} {c : C} (s s' : d ⟶ F.obj c), ∃ c' t, s ≫ F.map t = s' ≫ F.map t

tactic: intro d
state_before: case refine_1
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
⊢ ∀ (d : D), ∃ c, Nonempty (d ⟶ F.obj c)
state_after: case refine_1
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
⊢ ∃ c, Nonempty (d ⟶ F.obj c)

tactic: obtain ⟨f⟩ : Nonempty (StructuredArrow d F) := IsConnected.is_nonempty
state_before: case refine_1
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
⊢ ∃ c, Nonempty (d ⟶ F.obj c)
state_after: case refine_1.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
f : StructuredArrow d F
⊢ ∃ c, Nonempty (d ⟶ F.obj c)

tactic: exact ⟨_, ⟨f.hom⟩⟩
state_before: case refine_1.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
f : StructuredArrow d F
⊢ ∃ c, Nonempty (d ⟶ F.obj c)
state_after: no goals

tactic: intro d c s s'
state_before: case refine_2
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
⊢ ∀ {d : D} {c : C} (s s' : d ⟶ F.obj c), ∃ c' t, s ≫ F.map t = s' ≫ F.map t
state_after: case refine_2
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
⊢ ∃ c' t, s ≫ F.map t = s' ≫ F.map t

tactic: have : colimit.ι (F ⋙ coyoneda.obj (op d)) c s = colimit.ι (F ⋙ coyoneda.obj (op d)) c s' := by
  apply (Final.colimitCompCoyonedaIso F d).toEquiv.injective
  exact Subsingleton.elim _ _
state_before: case refine_2
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
⊢ ∃ c' t, s ≫ F.map t = s' ≫ F.map t
state_after: case refine_2
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
⊢ ∃ c' t, s ≫ F.map t = s' ≫ F.map t

tactic: obtain ⟨c', t₁, t₂, h⟩ := (Types.FilteredColimit.colimit_eq_iff.{v₁, v₁, v₁} _).mp this
state_before: case refine_2
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
⊢ ∃ c' t, s ≫ F.map t = s' ≫ F.map t
state_after: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : (F ⋙ coyoneda.obj { unop := d }).map t₁ s = (F ⋙ coyoneda.obj { unop := d }).map t₂ s'
⊢ ∃ c' t, s ≫ F.map t = s' ≫ F.map t

tactic: refine ⟨IsFiltered.coeq t₁ t₂, t₁ ≫ IsFiltered.coeqHom t₁ t₂, ?_⟩
state_before: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : (F ⋙ coyoneda.obj { unop := d }).map t₁ s = (F ⋙ coyoneda.obj { unop := d }).map t₂ s'
⊢ ∃ c' t, s ≫ F.map t = s' ≫ F.map t
state_after: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : (F ⋙ coyoneda.obj { unop := d }).map t₁ s = (F ⋙ coyoneda.obj { unop := d }).map t₂ s'
⊢ s ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂) = s' ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂)

tactic: conv_rhs => rw [IsFiltered.coeq_condition t₁ t₂]
state_before: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : (F ⋙ coyoneda.obj { unop := d }).map t₁ s = (F ⋙ coyoneda.obj { unop := d }).map t₂ s'
⊢ s ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂) = s' ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂)
state_after: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : (F ⋙ coyoneda.obj { unop := d }).map t₁ s = (F ⋙ coyoneda.obj { unop := d }).map t₂ s'
⊢ s ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂) = s' ≫ F.map (t₂ ≫ IsFiltered.coeqHom t₁ t₂)

tactic: dsimp only [comp_obj, coyoneda_obj_obj, unop_op, Functor.comp_map, coyoneda_obj_map] at h
state_before: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : (F ⋙ coyoneda.obj { unop := d }).map t₁ s = (F ⋙ coyoneda.obj { unop := d }).map t₂ s'
⊢ s ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂) = s' ≫ F.map (t₂ ≫ IsFiltered.coeqHom t₁ t₂)
state_after: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : s ≫ F.map t₁ = s' ≫ F.map t₂
⊢ s ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂) = s' ≫ F.map (t₂ ≫ IsFiltered.coeqHom t₁ t₂)

tactic: simp [reassoc_of% h]
state_before: case refine_2.intro.intro.intro
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
this : colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
c' : C
t₁ t₂ : c ⟶ c'
h : s ≫ F.map t₁ = s' ≫ F.map t₂
⊢ s ≫ F.map (t₁ ≫ IsFiltered.coeqHom t₁ t₂) = s' ≫ F.map (t₂ ≫ IsFiltered.coeqHom t₁ t₂)
state_after: no goals

tactic: apply (Final.colimitCompCoyonedaIso F d).toEquiv.injective
state_before: C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
⊢ colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s = colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s'
state_after: case a
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
⊢ (Final.colimitCompCoyonedaIso F d).toEquiv (colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s) =
    (Final.colimitCompCoyonedaIso F d).toEquiv (colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s')

tactic: exact Subsingleton.elim _ _
state_before: case a
C : Type v₁
inst✝² : Category.{v₁, v₁} C
D : Type u₂
inst✝¹ : Category.{v₁, u₂} D
F : C ⥤ D
inst✝ : IsFilteredOrEmpty C
hF : F.Final
d : D
c : C
s s' : d ⟶ F.obj c
⊢ (Final.colimitCompCoyonedaIso F d).toEquiv (colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s) =
    (Final.colimitCompCoyonedaIso F d).toEquiv (colimit.ι (F ⋙ coyoneda.obj { unop := d }) c s')
state_after: no goals