l3lab/ntp-mathlib huggingface dataset:
instance : Category (Grothendieck F) where
  Hom X Y := Grothendieck.Hom X Y
  id X := Grothendieck.id X
  comp := @fun X Y Z f g => Grothendieck.comp f g
  comp_id := @fun X Y f => by
    dsimp; ext
    · simp
    · dsimp
      rw [← NatIso.naturality_2 (eqToIso (F.map_id Y.base)) f.fiber]
      simp
  id_comp := @fun X Y f => by dsimp; ext <;> simp
  assoc := @fun W X Y Z f g h => by
    dsimp; ext
    · simp
    · dsimp
      rw [← NatIso.naturality_2 (eqToIso (F.map_comp _ _)) f.fiber]
      

Proof state:
case w_fiber
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.9489, u_1} C
inst✝ : Category.{?u.9493, u_2} D
F : C ⥤ Cat
W X Y Z : Grothendieck F
f : W ⟶ X
g : X ⟶ Y
h : Y ⟶ Z
⊢ eqToHom (_ : (F.map (f.base ≫ g.base ≫ h.base)).obj W.fiber = (F.map ((f.base ≫ g.base) ≫ h.base)).obj W.fiber) ≫
      eqToHom
          (_ :
            (F.map ((comp f g).base ≫ h.base)).obj W.fiber = (F.map h.base).obj ((F.map (comp f g).base).obj W.fiber)) ≫
        (F.map h.base).map
            (eqToHom (_ : (F.map (f.base ≫ g.base)).obj W.fiber = (F.map g.base).obj ((F.map f.base).obj W.fiber)) ≫
              (F.map g.base).map f.fiber ≫ g.fiber) ≫
          h.fiber =
    eqToHom
        (_ :
          (F.map (f.base ≫ (comp g h).base)).obj W.fiber = (F.map (comp g h).base).obj ((F.map f.base).obj W.fiber)) ≫
      ((eqToIso (_ : F.map (g.base ≫ h.base) = F.map g.base ≫ F.map h.base)).hom.app ((F.map f.base).obj W.fiber) ≫
          (F.map g.base ≫ F.map h.base).map f.fiber ≫
            (eqToIso (_ : F.map (g.base ≫ h.base) = F.map g.base ≫ F.map h.base)).inv.app X.fiber) ≫
        eqToHom (_ : (F.map (g.base ≫ h.base)).obj X.fiber = (F.map h.base).obj ((F.map g.base).obj X.fiber)) ≫
          (F.map h.base).map g.fiber ≫ h.fiber

Next tactic:
simp
@[simp]
theorem id_fiber' (X : Grothendieck F) :
    Hom.fiber (𝟙 X) = eqToHom (by 

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.19119, u_1} C
inst✝ : Category.{?u.19123, u_2} D
F : C ⥤ Cat
X : Grothendieck F
⊢ (F.map (𝟙 X).base).obj X.fiber = X.fiber

Next tactic:
erw [CategoryTheory.Functor.map_id, Functor.id_obj X.fiber]
theorem congr {X Y : Grothendieck F} {f g : X ⟶ Y} (h : f = g) :
    f.fiber = eqToHom (by 

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.20867, u_1} C
inst✝ : Category.{?u.20871, u_2} D
F : C ⥤ Cat
X Y : Grothendieck F
f g : X ⟶ Y
h : f = g
⊢ (F.map f.base).obj X.fiber = (F.map g.base).obj X.fiber

Next tactic:
subst h
theorem congr {X Y : Grothendieck F} {f g : X ⟶ Y} (h : f = g) :
    f.fiber = eqToHom (by subst h; 

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.20867, u_1} C
inst✝ : Category.{?u.20871, u_2} D
F : C ⥤ Cat
X Y : Grothendieck F
f : X ⟶ Y
⊢ (F.map f.base).obj X.fiber = (F.map f.base).obj X.fiber

Next tactic:
rfl
theorem congr {X Y : Grothendieck F} {f g : X ⟶ Y} (h : f = g) :
    f.fiber = eqToHom (by subst h; rfl) ≫ g.fiber := by
  

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{u_3, u_1} C
inst✝ : Category.{?u.20871, u_2} D
F : C ⥤ Cat
X Y : Grothendieck F
f g : X ⟶ Y
h : f = g
⊢ f.fiber = eqToHom (_ : (F.map f.base).obj X.fiber = (F.map g.base).obj X.fiber) ≫ g.fiber

Next tactic:
subst h
theorem congr {X Y : Grothendieck F} {f g : X ⟶ Y} (h : f = g) :
    f.fiber = eqToHom (by subst h; rfl) ≫ g.fiber := by
  subst h
  

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{u_3, u_1} C
inst✝ : Category.{?u.20871, u_2} D
F : C ⥤ Cat
X Y : Grothendieck F
f : X ⟶ Y
⊢ f.fiber = eqToHom (_ : (F.map f.base).obj X.fiber = (F.map f.base).obj X.fiber) ≫ f.fiber

Next tactic:
dsimp
theorem congr {X Y : Grothendieck F} {f g : X ⟶ Y} (h : f = g) :
    f.fiber = eqToHom (by subst h; rfl) ≫ g.fiber := by
  subst h
  dsimp
  

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{u_3, u_1} C
inst✝ : Category.{?u.20871, u_2} D
F : C ⥤ Cat
X Y : Grothendieck F
f : X ⟶ Y
⊢ f.fiber = 𝟙 ((F.map f.base).obj X.fiber) ≫ f.fiber

Next tactic:
simp
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
X : Grothendieck (G ⋙ typeToCat)
⊢ (𝟭 (Grothendieck (G ⋙ typeToCat))).obj X ≅ (grothendieckTypeToCatFunctor G ⋙ grothendieckTypeToCatInverse G).obj X

Next tactic:
rcases X with ⟨_, ⟨⟩⟩
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        

Proof state:
case mk.mk
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
base✝ : C
as✝ : G.obj base✝
⊢ (𝟭 (Grothendieck (G ⋙ typeToCat))).obj { base := base✝, fiber := { as := as✝ } } ≅
    (grothendieckTypeToCatFunctor G ⋙ grothendieckTypeToCatInverse G).obj { base := base✝, fiber := { as := as✝ } }

Next tactic:
exact Iso.refl _
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
⊢ ∀ {X Y : Grothendieck (G ⋙ typeToCat)} (f : X ⟶ Y),
    (𝟭 (Grothendieck (G ⋙ typeToCat))).map f ≫
        ((fun X =>
              Grothendieck.casesOn X fun base fiber =>
                Discrete.casesOn fiber fun as =>
                  Iso.refl ((𝟭 (Grothendieck (G ⋙ typeToCat))).obj { base := base, fiber := { as := as } }))
            Y).hom =
      ((fun X =>
              Grothendieck.casesOn X fun base fiber =>
                Discrete.casesOn fiber fun as =>
                  Iso.refl ((𝟭 (Grothendieck (G ⋙ typeToCat))).obj { base := base, fiber := { as := as } }))
            X).hom ≫
        (grothendieckTypeToCatFunctor G ⋙ grothendieckTypeToCatInverse G).map f

Next tactic:
rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        

Proof state:
case mk.mk.mk.mk.mk.up.up
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
base✝¹ : C
as✝¹ : G.obj base✝¹
base✝ : C
as✝ : G.obj base✝
base : { base := base✝¹, fiber := { as := as✝¹ } }.base ⟶ { base := base✝, fiber := { as := as✝ } }.base
f :
  (((G ⋙ typeToCat).map base).obj { base := base✝¹, fiber := { as := as✝¹ } }.fiber).as =
    { base := base✝, fiber := { as := as✝ } }.fiber.as
⊢ (𝟭 (Grothendieck (G ⋙ typeToCat))).map { base := base, fiber := { down := { down := f } } } ≫
      ((fun X =>
            Grothendieck.casesOn X fun base fiber =>
              Discrete.casesOn fiber fun as =>
                Iso.refl ((𝟭 (Grothendieck (G ⋙ typeToCat))).obj { base := base, fiber := { as := as } }))
          { base := base✝, fiber := { as := as✝ } }).hom =
    ((fun X =>
            Grothendieck.casesOn X fun base fiber =>
              Discrete.casesOn fiber fun as =>
                Iso.refl ((𝟭 (Grothendieck (G ⋙ typeToCat))).obj { base := base, fiber := { as := as } }))
          { base := base✝¹, fiber := { as := as✝¹ } }).hom ≫
      (grothendieckTypeToCatFunctor G ⋙ grothendieckTypeToCatInverse G).map
        { base := base, fiber := { down := { down := f } } }

Next tactic:
dsimp at *
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        dsimp at *
        

Proof state:
case mk.mk.mk.mk.mk.up.up
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
base✝¹ : C
as✝¹ : G.obj base✝¹
base✝ : C
as✝ : G.obj base✝
base : { base := base✝¹, fiber := { as := as✝¹ } }.base ⟶ { base := base✝, fiber := { as := as✝ } }.base
f :
  (((G ⋙ typeToCat).map base).obj { base := base✝¹, fiber := { as := as✝¹ } }.fiber).as =
    { base := base✝, fiber := { as := as✝ } }.fiber.as
⊢ { base := base, fiber := { down := { down := f } } } ≫ 𝟙 { base := base✝, fiber := { as := as✝ } } =
    𝟙 { base := base✝¹, fiber := { as := as✝¹ } } ≫
      (grothendieckTypeToCatInverse G).map
        ((grothendieckTypeToCatFunctor G).map { base := base, fiber := { down := { down := f } } })

Next tactic:
simp
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        dsimp at *
        simp
        

Proof state:
case mk.mk.mk.mk.mk.up.up
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
base✝¹ : C
as✝¹ : G.obj base✝¹
base✝ : C
as✝ : G.obj base✝
base : { base := base✝¹, fiber := { as := as✝¹ } }.base ⟶ { base := base✝, fiber := { as := as✝ } }.base
f :
  (((G ⋙ typeToCat).map base).obj { base := base✝¹, fiber := { as := as✝¹ } }.fiber).as =
    { base := base✝, fiber := { as := as✝ } }.fiber.as
⊢ { base := base, fiber := { down := { down := f } } } =
    (grothendieckTypeToCatInverse G).map
      ((grothendieckTypeToCatFunctor G).map { base := base, fiber := { down := { down := f } } })

Next tactic:
rfl
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        dsimp at *
        simp
        rfl)
  counitIso :=
    NatIso.ofComponents
      (fun X => by
        

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
X : Functor.Elements G
⊢ (grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj X ≅ (𝟭 (Functor.Elements G)).obj X

Next tactic:
cases X
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        dsimp at *
        simp
        rfl)
  counitIso :=
    NatIso.ofComponents
      (fun X => by
        cases X
        

Proof state:
case mk
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
fst✝ : C
snd✝ : G.obj fst✝
⊢ (grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj { fst := fst✝, snd := snd✝ } ≅
    (𝟭 (Functor.Elements G)).obj { fst := fst✝, snd := snd✝ }

Next tactic:
exact Iso.refl _
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        dsimp at *
        simp
        rfl)
  counitIso :=
    NatIso.ofComponents
      (fun X => by
        cases X
        exact Iso.refl _)
      (by
        

Proof state:
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
⊢ ∀ {X Y : Functor.Elements G} (f : X ⟶ Y),
    (grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).map f ≫
        ((fun X =>
              Sigma.casesOn (motive := fun t =>
                X = t →
                  ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj X ≅
                    (𝟭 (Functor.Elements G)).obj X))
                X
                (fun fst snd h =>
                  (_ : { fst := fst, snd := snd } = X) ▸
                    Iso.refl
                      ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj
                        { fst := fst, snd := snd }))
                (_ : X = X))
            Y).hom =
      ((fun X =>
              Sigma.casesOn (motive := fun t =>
                X = t →
                  ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj X ≅
                    (𝟭 (Functor.Elements G)).obj X))
                X
                (fun fst snd h =>
                  (_ : { fst := fst, snd := snd } = X) ▸
                    Iso.refl
                      ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj
                        { fst := fst, snd := snd }))
                (_ : X = X))
            X).hom ≫
        (𝟭 (Functor.Elements G)).map f

Next tactic:
rintro ⟨⟩ ⟨⟩ ⟨f, e⟩
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        dsimp at *
        simp
        rfl)
  counitIso :=
    NatIso.ofComponents
      (fun X => by
        cases X
        exact Iso.refl _)
      (by
        rintro ⟨⟩ ⟨⟩ ⟨f, e⟩
        

Proof state:
case mk.mk.mk
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
fst✝¹ : C
snd✝¹ : G.obj fst✝¹
fst✝ : C
snd✝ : G.obj fst✝
f : { fst := fst✝¹, snd := snd✝¹ }.fst ⟶ { fst := fst✝, snd := snd✝ }.fst
e : G.map f { fst := fst✝¹, snd := snd✝¹ }.snd = { fst := fst✝, snd := snd✝ }.snd
⊢ (grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).map { val := f, property := e } ≫
      ((fun X =>
            Sigma.casesOn (motive := fun t =>
              X = t →
                ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj X ≅
                  (𝟭 (Functor.Elements G)).obj X))
              X
              (fun fst snd h =>
                (_ : { fst := fst, snd := snd } = X) ▸
                  Iso.refl
                    ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj { fst := fst, snd := snd }))
              (_ : X = X))
          { fst := fst✝, snd := snd✝ }).hom =
    ((fun X =>
            Sigma.casesOn (motive := fun t =>
              X = t →
                ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj X ≅
                  (𝟭 (Functor.Elements G)).obj X))
              X
              (fun fst snd h =>
                (_ : { fst := fst, snd := snd } = X) ▸
                  Iso.refl
                    ((grothendieckTypeToCatInverse G ⋙ grothendieckTypeToCatFunctor G).obj { fst := fst, snd := snd }))
              (_ : X = X))
          { fst := fst✝¹, snd := snd✝¹ }).hom ≫
      (𝟭 (Functor.Elements G)).map { val := f, property := e }

Next tactic:
dsimp at *
/-- The Grothendieck construction applied to a functor to `Type`
(thought of as a functor to `Cat` by realising a type as a discrete category)
is the same as the 'category of elements' construction.
-/
-- See porting note on grothendieckTypeToCatInverse.
-- We just want to turn off grothendieckTypeToCat_inverse_map_fiber_down_down,
-- so have to list the complement here for `@[simps]`.
@[simps! functor_obj_fst functor_obj_snd functor_map_coe inverse_obj_base inverse_obj_fiber_as
  inverse_map_base unitIso_hom_app_base unitIso_hom_app_fiber unitIso_inv_app_base
  unitIso_inv_app_fiber counitIso_hom_app_coe counitIso_inv_app_coe]
def grothendieckTypeToCat : Grothendieck (G ⋙ typeToCat) ≌ G.Elements where
  functor := grothendieckTypeToCatFunctor G
  inverse := grothendieckTypeToCatInverse G
  unitIso :=
    NatIso.ofComponents
      (fun X => by
        rcases X with ⟨_, ⟨⟩⟩
        exact Iso.refl _)
      (by
        rintro ⟨_, ⟨⟩⟩ ⟨_, ⟨⟩⟩ ⟨base, ⟨⟨f⟩⟩⟩
        dsimp at *
        simp
        rfl)
  counitIso :=
    NatIso.ofComponents
      (fun X => by
        cases X
        exact Iso.refl _)
      (by
        rintro ⟨⟩ ⟨⟩ ⟨f, e⟩
        dsimp at *
        

Proof state:
case mk.mk.mk
C : Type u_1
D : Type u_2
inst✝¹ : Category.{?u.35528, u_1} C
inst✝ : Category.{?u.35532, u_2} D
F : C ⥤ Cat
G : C ⥤ Type w
fst✝¹ : C
snd✝¹ : G.obj fst✝¹
fst✝ : C
snd✝ : G.obj fst✝
f : { fst := fst✝¹, snd := snd✝¹ }.fst ⟶ { fst := fst✝, snd := snd✝ }.fst
e : G.map f { fst := fst✝¹, snd := snd✝¹ }.snd = { fst := fst✝, snd := snd✝ }.snd
⊢ (grothendieckTypeToCatFunctor G).map ((grothendieckTypeToCatInverse G).map { val := f, property := e }) ≫
      𝟙 ((grothendieckTypeToCatFunctor G).obj ((grothendieckTypeToCatInverse G).obj { fst := fst✝, snd := snd✝ })) =
    𝟙 ((grothendieckTypeToCatFunctor G).obj ((grothendieckTypeToCatInverse G).obj { fst := fst✝¹, snd := snd✝¹ })) ≫
      { val := f, property := e }

Next tactic:
simp