l3lab/ntp-mathlib huggingface dataset:
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
⊢ Function.Injective (colimitLimitToLimitColimit F)

Next tactic:
cases nonempty_fintype J
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    

Proof state:
case intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
⊢ Function.Injective (colimitLimitToLimitColimit F)

Next tactic:
intro x y h
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    

Proof state:
case intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
x y : colimit (curry.obj (swap K J ⋙ F) ⋙ lim)
h : colimitLimitToLimitColimit F x = colimitLimitToLimitColimit F y
⊢ x = y

Next tactic:
obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    

Proof state:
case intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
y : colimit (curry.obj (swap K J ⋙ F) ⋙ lim)
kx : K
x : (curry.obj (swap K J ⋙ F) ⋙ lim).obj kx
h : colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x) = colimitLimitToLimitColimit F y
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = y

Next tactic:
obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    

Proof state:
case intro.intro.intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : (curry.obj (swap K J ⋙ F) ⋙ lim).obj kx
ky : K
y : (curry.obj (swap K J ⋙ F) ⋙ lim).obj ky
h :
  colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x) =
    colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y)
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y

Next tactic:
dsimp at x y
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    dsimp at x y
    -- Since the images of `x` and `y` are equal in a limit, they are equal componentwise
    -- (indexed by `j : J`),
    

Proof state:
case intro.intro.intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : limit ((curry.obj (swap K J ⋙ F)).obj kx)
ky : K
y : limit ((curry.obj (swap K J ⋙ F)).obj ky)
h :
  colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x) =
    colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y)
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y

Next tactic:
replace h := fun j => congr_arg (limit.π (curry.obj F ⋙ colim) j) h
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    dsimp at x y
    -- Since the images of `x` and `y` are equal in a limit, they are equal componentwise
    -- (indexed by `j : J`),
    replace h := fun j => congr_arg (limit.π (curry.obj F ⋙ colim) j) h
    -- and they are equations in a filtered colimit,
    -- so for each `j` we have some place `k j` to the right of both `kx` and `ky`
    

Proof state:
case intro.intro.intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : limit ((curry.obj (swap K J ⋙ F)).obj kx)
ky : K
y : limit ((curry.obj (swap K J ⋙ F)).obj ky)
h :
  ∀ (j : J),
    limit.π (curry.obj F ⋙ colim) j (colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x)) =
      limit.π (curry.obj F ⋙ colim) j (colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y))
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y

Next tactic:
simp? [colimit_eq_iff.{v, v}] at h says
      simp only [Functor.comp_obj, colim_obj, ι_colimitLimitToLimitColimit_π_apply,
        colimit_eq_iff.{v, v}, curry_obj_obj_obj, curry_obj_obj_map] at h
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    dsimp at x y
    -- Since the images of `x` and `y` are equal in a limit, they are equal componentwise
    -- (indexed by `j : J`),
    replace h := fun j => congr_arg (limit.π (curry.obj F ⋙ colim) j) h
    -- and they are equations in a filtered colimit,
    -- so for each `j` we have some place `k j` to the right of both `kx` and `ky`
    simp? [colimit_eq_iff.{v, v}] at h says
      

Proof state:
case intro.intro.intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : limit ((curry.obj (swap K J ⋙ F)).obj kx)
ky : K
y : limit ((curry.obj (swap K J ⋙ F)).obj ky)
h :
  ∀ (j : J),
    limit.π (curry.obj F ⋙ colim) j (colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x)) =
      limit.π (curry.obj F ⋙ colim) j (colimitLimitToLimitColimit F (colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y))
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y

Next tactic:
simp only [Functor.comp_obj, colim_obj, ι_colimitLimitToLimitColimit_π_apply,
        colimit_eq_iff.{v, v}, curry_obj_obj_obj, curry_obj_obj_map] at h
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    dsimp at x y
    -- Since the images of `x` and `y` are equal in a limit, they are equal componentwise
    -- (indexed by `j : J`),
    replace h := fun j => congr_arg (limit.π (curry.obj F ⋙ colim) j) h
    -- and they are equations in a filtered colimit,
    -- so for each `j` we have some place `k j` to the right of both `kx` and `ky`
    simp? [colimit_eq_iff.{v, v}] at h says
      simp only [Functor.comp_obj, colim_obj, ι_colimitLimitToLimitColimit_π_apply,
        colimit_eq_iff.{v, v}, curry_obj_obj_obj, curry_obj_obj_map] at h
    

Proof state:
case intro.intro.intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : limit ((curry.obj (swap K J ⋙ F)).obj kx)
ky : K
y : limit ((curry.obj (swap K J ⋙ F)).obj ky)
h :
  ∀ (j : J),
    ∃ k f g,
      F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
        F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y)
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y

Next tactic:
let k j := (h j).choose
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    dsimp at x y
    -- Since the images of `x` and `y` are equal in a limit, they are equal componentwise
    -- (indexed by `j : J`),
    replace h := fun j => congr_arg (limit.π (curry.obj F ⋙ colim) j) h
    -- and they are equations in a filtered colimit,
    -- so for each `j` we have some place `k j` to the right of both `kx` and `ky`
    simp? [colimit_eq_iff.{v, v}] at h says
      simp only [Functor.comp_obj, colim_obj, ι_colimitLimitToLimitColimit_π_apply,
        colimit_eq_iff.{v, v}, curry_obj_obj_obj, curry_obj_obj_map] at h
    let k j := (h j).choose
    

Proof state:
case intro.intro.intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : limit ((curry.obj (swap K J ⋙ F)).obj kx)
ky : K
y : limit ((curry.obj (swap K J ⋙ F)).obj ky)
h :
  ∀ (j : J),
    ∃ k f g,
      F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
        F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y)
k : J → K :=
  fun j =>
    Exists.choose
      (_ :
        ∃ k f g,
          F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
            F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y))
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y

Next tactic:
let f : ∀ j, kx ⟶ k j := fun j => (h j).choose_spec.choose
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
-/
theorem colimitLimitToLimitColimit_injective :
    Function.Injective (colimitLimitToLimitColimit F) := by
  classical
    cases nonempty_fintype J
    -- Suppose we have two terms `x y` in the colimit (over `K`) of the limits (over `J`),
    -- and that these have the same image under `colimitLimitToLimitColimit F`.
    intro x y h
    -- These elements of the colimit have representatives somewhere:
    obtain ⟨kx, x, rfl⟩ := jointly_surjective'.{v, v} x
    obtain ⟨ky, y, rfl⟩ := jointly_surjective'.{v, v} y
    dsimp at x y
    -- Since the images of `x` and `y` are equal in a limit, they are equal componentwise
    -- (indexed by `j : J`),
    replace h := fun j => congr_arg (limit.π (curry.obj F ⋙ colim) j) h
    -- and they are equations in a filtered colimit,
    -- so for each `j` we have some place `k j` to the right of both `kx` and `ky`
    simp? [colimit_eq_iff.{v, v}] at h says
      simp only [Functor.comp_obj, colim_obj, ι_colimitLimitToLimitColimit_π_apply,
        colimit_eq_iff.{v, v}, curry_obj_obj_obj, curry_obj_obj_map] at h
    let k j := (h j).choose
    let f : ∀ j, kx ⟶ k j := fun j => (h j).choose_spec.choose
    

Proof state:
case intro.intro.intro.intro.intro
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : Finite J
val✝ : Fintype J
kx : K
x : limit ((curry.obj (swap K J ⋙ F)).obj kx)
ky : K
y : limit ((curry.obj (swap K J ⋙ F)).obj ky)
h :
  ∀ (j : J),
    ∃ k f g,
      F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
        F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y)
k : J → K :=
  fun j =>
    Exists.choose
      (_ :
        ∃ k f g,
          F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
            F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y))
f : (j : J) → kx ⟶ k j :=
  fun j =>
    Exists.choose
      (_ :
        ∃ f g,
          F.map (𝟙 j, f) (limit.π ((curry.obj (swap K J ⋙ F)).obj kx) j x) =
            F.map (𝟙 j, g) (limit.π ((curry.obj (swap K J ⋙ F)).obj ky) j y))
⊢ colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) kx x = colimit.ι (curry.obj (swap K J ⋙ F) ⋙ lim) ky y

Next tactic:
let g : ∀ j, ky ⟶ k j := fun j => (h j).choose_spec.choose_spec.choose
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
although with different names.
-/
theorem colimitLimitToLimitColimit_surjective :
    Function.Surjective (colimitLimitToLimitColimit F) := by
  classical
    -- We begin with some element `x` in the limit (over J) over the colimits (over K),
    

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : FinCategory J
⊢ Function.Surjective (colimitLimitToLimitColimit F)

Next tactic:
intro x
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
although with different names.
-/
theorem colimitLimitToLimitColimit_surjective :
    Function.Surjective (colimitLimitToLimitColimit F) := by
  classical
    -- We begin with some element `x` in the limit (over J) over the colimits (over K),
    intro x
    -- This consists of some coherent family of elements in the various colimits,
    -- and so our first task is to pick representatives of these elements.
    

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : FinCategory J
x : limit (curry.obj F ⋙ colim)
⊢ ∃ a, colimitLimitToLimitColimit F a = x

Next tactic:
have z := fun j => jointly_surjective'.{v, v} (limit.π (curry.obj F ⋙ Limits.colim) j x)
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
although with different names.
-/
theorem colimitLimitToLimitColimit_surjective :
    Function.Surjective (colimitLimitToLimitColimit F) := by
  classical
    -- We begin with some element `x` in the limit (over J) over the colimits (over K),
    intro x
    -- This consists of some coherent family of elements in the various colimits,
    -- and so our first task is to pick representatives of these elements.
    have z := fun j => jointly_surjective'.{v, v} (limit.π (curry.obj F ⋙ Limits.colim) j x)
    -- `k : J ⟶ K` records where the representative of the
    -- element in the `j`-th element of `x` lives
    

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : FinCategory J
x : limit (curry.obj F ⋙ colim)
z : ∀ (j : J), ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x
⊢ ∃ a, colimitLimitToLimitColimit F a = x

Next tactic:
let k : J → K := fun j => (z j).choose
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
although with different names.
-/
theorem colimitLimitToLimitColimit_surjective :
    Function.Surjective (colimitLimitToLimitColimit F) := by
  classical
    -- We begin with some element `x` in the limit (over J) over the colimits (over K),
    intro x
    -- This consists of some coherent family of elements in the various colimits,
    -- and so our first task is to pick representatives of these elements.
    have z := fun j => jointly_surjective'.{v, v} (limit.π (curry.obj F ⋙ Limits.colim) j x)
    -- `k : J ⟶ K` records where the representative of the
    -- element in the `j`-th element of `x` lives
    let k : J → K := fun j => (z j).choose
    -- `y j : F.obj (j, k j)` is the representative
    

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : FinCategory J
x : limit (curry.obj F ⋙ colim)
z : ∀ (j : J), ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x
k : J → K :=
  fun j => Exists.choose (_ : ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x)
⊢ ∃ a, colimitLimitToLimitColimit F a = x

Next tactic:
let y : ∀ j, F.obj (j, k j) := fun j => (z j).choose_spec.choose
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
although with different names.
-/
theorem colimitLimitToLimitColimit_surjective :
    Function.Surjective (colimitLimitToLimitColimit F) := by
  classical
    -- We begin with some element `x` in the limit (over J) over the colimits (over K),
    intro x
    -- This consists of some coherent family of elements in the various colimits,
    -- and so our first task is to pick representatives of these elements.
    have z := fun j => jointly_surjective'.{v, v} (limit.π (curry.obj F ⋙ Limits.colim) j x)
    -- `k : J ⟶ K` records where the representative of the
    -- element in the `j`-th element of `x` lives
    let k : J → K := fun j => (z j).choose
    -- `y j : F.obj (j, k j)` is the representative
    let y : ∀ j, F.obj (j, k j) := fun j => (z j).choose_spec.choose
    -- and we record that these representatives, when mapped back into the relevant colimits,
    -- are actually the components of `x`.
    

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : FinCategory J
x : limit (curry.obj F ⋙ colim)
z : ∀ (j : J), ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x
k : J → K :=
  fun j => Exists.choose (_ : ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x)
y : (j : J) → F.obj (j, k j) :=
  fun j =>
    Exists.choose
      (_ :
        ∃ y,
          colimit.ι ((curry.obj F).obj j)
              (Exists.choose (_ : ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x))
              y =
            limit.π (curry.obj F ⋙ colim) j x)
⊢ ∃ a, colimitLimitToLimitColimit F a = x

Next tactic:
have e : ∀ j,
        colimit.ι ((curry.obj F).obj j) (k j) (y j) = limit.π (curry.obj F ⋙ Limits.colim) j x :=
      fun j => (z j).choose_spec.choose_spec
/-- This follows this proof from
* Borceux, Handbook of categorical algebra 1, Theorem 2.13.4
although with different names.
-/
theorem colimitLimitToLimitColimit_surjective :
    Function.Surjective (colimitLimitToLimitColimit F) := by
  classical
    -- We begin with some element `x` in the limit (over J) over the colimits (over K),
    intro x
    -- This consists of some coherent family of elements in the various colimits,
    -- and so our first task is to pick representatives of these elements.
    have z := fun j => jointly_surjective'.{v, v} (limit.π (curry.obj F ⋙ Limits.colim) j x)
    -- `k : J ⟶ K` records where the representative of the
    -- element in the `j`-th element of `x` lives
    let k : J → K := fun j => (z j).choose
    -- `y j : F.obj (j, k j)` is the representative
    let y : ∀ j, F.obj (j, k j) := fun j => (z j).choose_spec.choose
    -- and we record that these representatives, when mapped back into the relevant colimits,
    -- are actually the components of `x`.
    have e : ∀ j,
        colimit.ι ((curry.obj F).obj j) (k j) (y j) = limit.π (curry.obj F ⋙ Limits.colim) j x :=
      fun j => (z j).choose_spec.choose_spec
    

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
F : J × K ⥤ Type v
inst✝¹ : IsFiltered K
inst✝ : FinCategory J
x : limit (curry.obj F ⋙ colim)
z : ∀ (j : J), ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x
k : J → K :=
  fun j => Exists.choose (_ : ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x)
y : (j : J) → F.obj (j, k j) :=
  fun j =>
    Exists.choose
      (_ :
        ∃ y,
          colimit.ι ((curry.obj F).obj j)
              (Exists.choose (_ : ∃ j_1 y, colimit.ι ((curry.obj F).obj j) j_1 y = limit.π (curry.obj F ⋙ colim) j x))
              y =
            limit.π (curry.obj F ⋙ colim) j x)
e : ∀ (j : J), colimit.ι ((curry.obj F).obj j) (k j) (y j) = limit.π (curry.obj F ⋙ colim) j x
⊢ ∃ a, colimitLimitToLimitColimit F a = x

Next tactic:
clear_value k y