l3lab/ntp-mathlib huggingface dataset:
/-- The components of the colimit of a diagram of `PresheafedSpace C` is obtained
via taking componentwise limits.
-/
def colimitPresheafObjIsoComponentwiseLimit (F : J ⥤ PresheafedSpace.{_, _, v} C) [HasColimit F]
    (U : Opens (Limits.colimit F).carrier) :
    (Limits.colimit F).presheaf.obj (op U) ≅ limit (componentwiseDiagram F U) := by
  refine'
    ((sheafIsoOfIso (colimit.isoColimitCocone ⟨_, colimitCoconeIsColimit F⟩).symm).app
          (op U)).trans
      _
  refine' (limitObjIsoLimitCompEvaluation _ _).trans (Limits.lim.mapIso _)
  fapply NatIso.ofComponents
  · intro X
    refine' (F.obj (unop X)).presheaf.mapIso (eqToIso _)
    simp only [Functor.op_obj, unop_op, op_inj_iff, Opens.map_coe, SetLike.ext'_iff,
      Set.preimage_preimage]
    refine congr_arg (Set.preimage . U.1) (funext fun x => ?_)
    erw [← comp_app]
    

Proof state:
case app
J : Type u'
inst✝⁵ : Category.{v', u'} J
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : HasColimitsOfShape J TopCat
inst✝² : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝¹ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
inst✝ : HasColimit F
U : Opens ↑↑(Limits.colimit F)
X : Jᵒᵖ
x : (CategoryTheory.forget TopCat).obj ((F ⋙ forget C).obj X.unop)
⊢ (colimit.ι (F ⋙ forget C) X.unop ≫
        (colimit.isoColimitCocone { cocone := colimitCocone F, isColimit := colimitCoconeIsColimit F }).symm.hom.base)
      x =
    (colimit.ι F X.unop).base x

Next tactic:
congr
/-- The components of the colimit of a diagram of `PresheafedSpace C` is obtained
via taking componentwise limits.
-/
def colimitPresheafObjIsoComponentwiseLimit (F : J ⥤ PresheafedSpace.{_, _, v} C) [HasColimit F]
    (U : Opens (Limits.colimit F).carrier) :
    (Limits.colimit F).presheaf.obj (op U) ≅ limit (componentwiseDiagram F U) := by
  refine'
    ((sheafIsoOfIso (colimit.isoColimitCocone ⟨_, colimitCoconeIsColimit F⟩).symm).app
          (op U)).trans
      _
  refine' (limitObjIsoLimitCompEvaluation _ _).trans (Limits.lim.mapIso _)
  fapply NatIso.ofComponents
  · intro X
    refine' (F.obj (unop X)).presheaf.mapIso (eqToIso _)
    simp only [Functor.op_obj, unop_op, op_inj_iff, Opens.map_coe, SetLike.ext'_iff,
      Set.preimage_preimage]
    refine congr_arg (Set.preimage . U.1) (funext fun x => ?_)
    erw [← comp_app]
    congr
    

Proof state:
case app.e_a
J : Type u'
inst✝⁵ : Category.{v', u'} J
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : HasColimitsOfShape J TopCat
inst✝² : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝¹ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
inst✝ : HasColimit F
U : Opens ↑↑(Limits.colimit F)
X : Jᵒᵖ
x : (CategoryTheory.forget TopCat).obj ((F ⋙ forget C).obj X.unop)
⊢ colimit.ι (F ⋙ forget C) X.unop ≫
      (colimit.isoColimitCocone { cocone := colimitCocone F, isColimit := colimitCoconeIsColimit F }).symm.hom.base =
    (colimit.ι F X.unop).base

Next tactic:
exact ι_preservesColimitsIso_inv (forget C) F (unop X)
/-- The components of the colimit of a diagram of `PresheafedSpace C` is obtained
via taking componentwise limits.
-/
def colimitPresheafObjIsoComponentwiseLimit (F : J ⥤ PresheafedSpace.{_, _, v} C) [HasColimit F]
    (U : Opens (Limits.colimit F).carrier) :
    (Limits.colimit F).presheaf.obj (op U) ≅ limit (componentwiseDiagram F U) := by
  refine'
    ((sheafIsoOfIso (colimit.isoColimitCocone ⟨_, colimitCoconeIsColimit F⟩).symm).app
          (op U)).trans
      _
  refine' (limitObjIsoLimitCompEvaluation _ _).trans (Limits.lim.mapIso _)
  fapply NatIso.ofComponents
  · intro X
    refine' (F.obj (unop X)).presheaf.mapIso (eqToIso _)
    simp only [Functor.op_obj, unop_op, op_inj_iff, Opens.map_coe, SetLike.ext'_iff,
      Set.preimage_preimage]
    refine congr_arg (Set.preimage . U.1) (funext fun x => ?_)
    erw [← comp_app]
    congr
    exact ι_preservesColimitsIso_inv (forget C) F (unop X)
  · 

Proof state:
case naturality
J : Type u'
inst✝⁵ : Category.{v', u'} J
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : HasColimitsOfShape J TopCat
inst✝² : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝¹ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
inst✝ : HasColimit F
U : Opens ↑↑(Limits.colimit F)
⊢ autoParam
    (∀ {X Y : Jᵒᵖ} (f : X ⟶ Y),
      ((pushforwardDiagramToColimit F).leftOp ⋙
                (evaluation (Opens ↑↑{ cocone := colimitCocone F, isColimit := colimitCoconeIsColimit F }.cocone.pt)ᵒᵖ
                      C).obj
                  ((Opens.map
                          (colimit.isoColimitCocone
                                  { cocone := colimitCocone F,
                                    isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                    (op U))).map
            f ≫
          ((F.obj Y.unop).presheaf.mapIso
              (eqToIso
                (_ :
                  (Opens.map (colimit.ι (F ⋙ forget C) Y.unop)).op.obj
                      ((Opens.map
                              (colimit.isoColimitCocone
                                      { cocone := colimitCocone F,
                                        isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                        (op U)) =
                    op ((Opens.map (colimit.ι F Y.unop).base).obj U)))).hom =
        ((F.obj X.unop).presheaf.mapIso
              (eqToIso
                (_ :
                  (Opens.map (colimit.ι (F ⋙ forget C) X.unop)).op.obj
                      ((Opens.map
                              (colimit.isoColimitCocone
                                      { cocone := colimitCocone F,
                                        isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                        (op U)) =
                    op ((Opens.map (colimit.ι F X.unop).base).obj U)))).hom ≫
          (componentwiseDiagram F U).map f)
    _auto✝

Next tactic:
intro X Y f
/-- The components of the colimit of a diagram of `PresheafedSpace C` is obtained
via taking componentwise limits.
-/
def colimitPresheafObjIsoComponentwiseLimit (F : J ⥤ PresheafedSpace.{_, _, v} C) [HasColimit F]
    (U : Opens (Limits.colimit F).carrier) :
    (Limits.colimit F).presheaf.obj (op U) ≅ limit (componentwiseDiagram F U) := by
  refine'
    ((sheafIsoOfIso (colimit.isoColimitCocone ⟨_, colimitCoconeIsColimit F⟩).symm).app
          (op U)).trans
      _
  refine' (limitObjIsoLimitCompEvaluation _ _).trans (Limits.lim.mapIso _)
  fapply NatIso.ofComponents
  · intro X
    refine' (F.obj (unop X)).presheaf.mapIso (eqToIso _)
    simp only [Functor.op_obj, unop_op, op_inj_iff, Opens.map_coe, SetLike.ext'_iff,
      Set.preimage_preimage]
    refine congr_arg (Set.preimage . U.1) (funext fun x => ?_)
    erw [← comp_app]
    congr
    exact ι_preservesColimitsIso_inv (forget C) F (unop X)
  · intro X Y f
    

Proof state:
case naturality
J : Type u'
inst✝⁵ : Category.{v', u'} J
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : HasColimitsOfShape J TopCat
inst✝² : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝¹ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
inst✝ : HasColimit F
U : Opens ↑↑(Limits.colimit F)
X Y : Jᵒᵖ
f : X ⟶ Y
⊢ ((pushforwardDiagramToColimit F).leftOp ⋙
            (evaluation (Opens ↑↑{ cocone := colimitCocone F, isColimit := colimitCoconeIsColimit F }.cocone.pt)ᵒᵖ
                  C).obj
              ((Opens.map
                      (colimit.isoColimitCocone
                              { cocone := colimitCocone F,
                                isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                (op U))).map
        f ≫
      ((F.obj Y.unop).presheaf.mapIso
          (eqToIso
            (_ :
              (Opens.map (colimit.ι (F ⋙ forget C) Y.unop)).op.obj
                  ((Opens.map
                          (colimit.isoColimitCocone
                                  { cocone := colimitCocone F,
                                    isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                    (op U)) =
                op ((Opens.map (colimit.ι F Y.unop).base).obj U)))).hom =
    ((F.obj X.unop).presheaf.mapIso
          (eqToIso
            (_ :
              (Opens.map (colimit.ι (F ⋙ forget C) X.unop)).op.obj
                  ((Opens.map
                          (colimit.isoColimitCocone
                                  { cocone := colimitCocone F,
                                    isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                    (op U)) =
                op ((Opens.map (colimit.ι F X.unop).base).obj U)))).hom ≫
      (componentwiseDiagram F U).map f

Next tactic:
change ((F.map f.unop).c.app _ ≫ _ ≫ _) ≫ (F.obj (unop Y)).presheaf.map _ = _ ≫ _
/-- The components of the colimit of a diagram of `PresheafedSpace C` is obtained
via taking componentwise limits.
-/
def colimitPresheafObjIsoComponentwiseLimit (F : J ⥤ PresheafedSpace.{_, _, v} C) [HasColimit F]
    (U : Opens (Limits.colimit F).carrier) :
    (Limits.colimit F).presheaf.obj (op U) ≅ limit (componentwiseDiagram F U) := by
  refine'
    ((sheafIsoOfIso (colimit.isoColimitCocone ⟨_, colimitCoconeIsColimit F⟩).symm).app
          (op U)).trans
      _
  refine' (limitObjIsoLimitCompEvaluation _ _).trans (Limits.lim.mapIso _)
  fapply NatIso.ofComponents
  · intro X
    refine' (F.obj (unop X)).presheaf.mapIso (eqToIso _)
    simp only [Functor.op_obj, unop_op, op_inj_iff, Opens.map_coe, SetLike.ext'_iff,
      Set.preimage_preimage]
    refine congr_arg (Set.preimage . U.1) (funext fun x => ?_)
    erw [← comp_app]
    congr
    exact ι_preservesColimitsIso_inv (forget C) F (unop X)
  · intro X Y f
    change ((F.map f.unop).c.app _ ≫ _ ≫ _) ≫ (F.obj (unop Y)).presheaf.map _ = _ ≫ _
    rw [TopCat.Presheaf.Pushforward.comp_inv_app]
    erw [Category.id_comp]
    

Proof state:
case naturality
J : Type u'
inst✝⁵ : Category.{v', u'} J
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : HasColimitsOfShape J TopCat
inst✝² : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝¹ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
inst✝ : HasColimit F
U : Opens ↑↑(Limits.colimit F)
X Y : Jᵒᵖ
f : X ⟶ Y
⊢ ((F.map f.unop).c.app
          ((Opens.map (colimit.ι (F ⋙ forget C) X.unop)).op.obj
            ((Opens.map
                    (colimit.isoColimitCocone
                            { cocone := colimitCocone F, isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
              (op U))) ≫
        (pushforwardEq
                (_ : (F ⋙ forget C).map f.unop ≫ colimit.ι (F ⋙ forget C) X.unop = colimit.ι (F ⋙ forget C) Y.unop)
                (F.obj Y.unop).presheaf).hom.app
          ((Opens.map
                  (colimit.isoColimitCocone
                          { cocone := colimitCocone F, isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
            (op U))) ≫
      (F.obj Y.unop).presheaf.map
        (eqToIso
            (_ :
              (Opens.map (colimit.ι (F ⋙ forget C) Y.unop)).op.obj
                  ((Opens.map
                          (colimit.isoColimitCocone
                                  { cocone := colimitCocone F,
                                    isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                    (op U)) =
                op ((Opens.map (colimit.ι F Y.unop).base).obj U))).hom =
    ((F.obj X.unop).presheaf.mapIso
          (eqToIso
            (_ :
              (Opens.map (colimit.ι (F ⋙ forget C) X.unop)).op.obj
                  ((Opens.map
                          (colimit.isoColimitCocone
                                  { cocone := colimitCocone F,
                                    isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                    (op U)) =
                op ((Opens.map (colimit.ι F X.unop).base).obj U)))).hom ≫
      (componentwiseDiagram F U).map f

Next tactic:
rw [Category.assoc]
@[simp]
theorem colimitPresheafObjIsoComponentwiseLimit_inv_ι_app (F : J ⥤ PresheafedSpace.{_, _, v} C)
    (U : Opens (Limits.colimit F).carrier) (j : J) :
    (colimitPresheafObjIsoComponentwiseLimit F U).inv ≫ (colimit.ι F j).c.app (op U) =
      limit.π _ (op j) := by
  

Proof state:
J : Type u'
inst✝⁴ : Category.{v', u'} J
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasColimitsOfShape J TopCat
inst✝¹ : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
U : Opens ↑↑(Limits.colimit F)
j : J
⊢ (colimitPresheafObjIsoComponentwiseLimit F U).inv ≫ (colimit.ι F j).c.app (op U) =
    limit.π (componentwiseDiagram F U) (op j)

Next tactic:
delta colimitPresheafObjIsoComponentwiseLimit
@[simp]
theorem colimitPresheafObjIsoComponentwiseLimit_inv_ι_app (F : J ⥤ PresheafedSpace.{_, _, v} C)
    (U : Opens (Limits.colimit F).carrier) (j : J) :
    (colimitPresheafObjIsoComponentwiseLimit F U).inv ≫ (colimit.ι F j).c.app (op U) =
      limit.π _ (op j) := by
  delta colimitPresheafObjIsoComponentwiseLimit
  

Proof state:
J : Type u'
inst✝⁴ : Category.{v', u'} J
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasColimitsOfShape J TopCat
inst✝¹ : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
U : Opens ↑↑(Limits.colimit F)
j : J
⊢ ((sheafIsoOfIso
                (colimit.isoColimitCocone
                    { cocone := colimitCocone F, isColimit := colimitCoconeIsColimit F }).symm).app
            (op U) ≪≫
          limitObjIsoLimitCompEvaluation (pushforwardDiagramToColimit F).leftOp
              ((Opens.map
                      (colimit.isoColimitCocone
                              { cocone := colimitCocone F,
                                isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                (op U)) ≪≫
            Limits.lim.mapIso
              (NatIso.ofComponents fun X =>
                (F.obj X.unop).presheaf.mapIso
                  (eqToIso
                    (_ :
                      (Opens.map (colimit.ι (F ⋙ forget C) X.unop)).op.obj
                          ((Opens.map
                                  (colimit.isoColimitCocone
                                          { cocone := colimitCocone F,
                                            isColimit := colimitCoconeIsColimit F }).symm.hom.base).op.obj
                            (op U)) =
                        op ((Opens.map (colimit.ι F X.unop).base).obj U))))).inv ≫
      (colimit.ι F j).c.app (op U) =
    limit.π (componentwiseDiagram F U) (op j)

Next tactic:
rw [Iso.trans_inv, Iso.trans_inv, Iso.app_inv, sheafIsoOfIso_inv, pushforwardToOfIso_app,
    congr_app (Iso.symm_inv _)]
@[simp]
theorem colimitPresheafObjIsoComponentwiseLimit_hom_π (F : J ⥤ PresheafedSpace.{_, _, v} C)
    (U : Opens (Limits.colimit F).carrier) (j : J) :
    (colimitPresheafObjIsoComponentwiseLimit F U).hom ≫ limit.π _ (op j) =
      (colimit.ι F j).c.app (op U) :=
  by 

Proof state:
J : Type u'
inst✝⁴ : Category.{v', u'} J
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : HasColimitsOfShape J TopCat
inst✝¹ : ∀ (X : TopCat), HasLimitsOfShape Jᵒᵖ (Presheaf C X)
inst✝ : HasLimitsOfShape Jᵒᵖ C
F : J ⥤ PresheafedSpace C
U : Opens ↑↑(Limits.colimit F)
j : J
⊢ (colimitPresheafObjIsoComponentwiseLimit F U).hom ≫ limit.π (componentwiseDiagram F U) (op j) =
    (colimit.ι F j).c.app (op U)

Next tactic:
rw [← Iso.eq_inv_comp, colimitPresheafObjIsoComponentwiseLimit_inv_ι_app]
instance {α : Type*} [Fintype α] : Fintype (Option α) :=
  ⟨Finset.insertNone univ, fun a => by 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Fintype α
a : Option α
⊢ a ∈ insertNone univ

Next tactic:
simp
@[simp]
theorem Fintype.card_option {α : Type*} [Fintype α] :
    Fintype.card (Option α) = Fintype.card α + 1 :=
  (Finset.card_cons (by 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
inst✝ : Fintype α
⊢ none ∉ map Embedding.some univ

Next tactic:
simp
/-- A recursor principle for finite types, analogous to `Nat.rec`. It effectively says
that every `Fintype` is either `Empty` or `Option α`, up to an `Equiv`. -/
def truncRecEmptyOption {P : Type u → Sort v} (of_equiv : ∀ {α β}, α ≃ β → P α → P β)
    (h_empty : P PEmpty) (h_option : ∀ {α} [Fintype α] [DecidableEq α], P α → P (Option α))
    (α : Type u) [Fintype α] [DecidableEq α] : Trunc (P α) := by
  suffices ∀ n : ℕ, Trunc (P (ULift <| Fin n)) by
    apply Trunc.bind (this (Fintype.card α))
    intro h
    apply Trunc.map _ (Fintype.truncEquivFin α)
    intro e
    exact of_equiv (Equiv.ulift.trans e.symm) h
  apply ind where
    -- porting note: do a manual recursion, instead of `induction` tactic,
    -- to ensure the result is computable
    /-- Internal induction hypothesis -/
    ind : ∀ n : ℕ, Trunc (P (ULift <| Fin n))
    | Nat.zero => by
          

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
P : Type u → Sort v
of_equiv : {α β : Type u} → α ≃ β → P α → P β
h_empty : P PEmpty.{u + 1}
h_option : {α : Type u} → [inst : Fintype α] → [inst : DecidableEq α] → P α → P (Option α)
α : Type u
inst✝¹ : Fintype α
inst✝ : DecidableEq α
⊢ Trunc (P (ULift.{u, 0} (Fin zero)))

Next tactic:
have : card PEmpty = card (ULift (Fin 0)) := by simp only [card_fin, card_pempty,
                                                                     card_ulift]
/-- A recursor principle for finite types, analogous to `Nat.rec`. It effectively says
that every `Fintype` is either `Empty` or `Option α`, up to an `Equiv`. -/
def truncRecEmptyOption {P : Type u → Sort v} (of_equiv : ∀ {α β}, α ≃ β → P α → P β)
    (h_empty : P PEmpty) (h_option : ∀ {α} [Fintype α] [DecidableEq α], P α → P (Option α))
    (α : Type u) [Fintype α] [DecidableEq α] : Trunc (P α) := by
  suffices ∀ n : ℕ, Trunc (P (ULift <| Fin n)) by
    apply Trunc.bind (this (Fintype.card α))
    intro h
    apply Trunc.map _ (Fintype.truncEquivFin α)
    intro e
    exact of_equiv (Equiv.ulift.trans e.symm) h
  apply ind where
    -- porting note: do a manual recursion, instead of `induction` tactic,
    -- to ensure the result is computable
    /-- Internal induction hypothesis -/
    ind : ∀ n : ℕ, Trunc (P (ULift <| Fin n))
    | Nat.zero => by
          have : card PEmpty = card (ULift (Fin 0)) := by 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
P : Type u → Sort v
of_equiv : {α β : Type u} → α ≃ β → P α → P β
h_empty : P PEmpty.{u + 1}
h_option : {α : Type u} → [inst : Fintype α] → [inst : DecidableEq α] → P α → P (Option α)
α : Type u
inst✝¹ : Fintype α
inst✝ : DecidableEq α
⊢ card PEmpty.{?u.5312 + 1} = card (ULift.{?u.5322, 0} (Fin 0))

Next tactic:
simp only [card_fin, card_pempty,
                                                                     card_ulift]
/-- A recursor principle for finite types, analogous to `Nat.rec`. It effectively says
that every `Fintype` is either `Empty` or `Option α`, up to an `Equiv`. -/
def truncRecEmptyOption {P : Type u → Sort v} (of_equiv : ∀ {α β}, α ≃ β → P α → P β)
    (h_empty : P PEmpty) (h_option : ∀ {α} [Fintype α] [DecidableEq α], P α → P (Option α))
    (α : Type u) [Fintype α] [DecidableEq α] : Trunc (P α) := by
  suffices ∀ n : ℕ, Trunc (P (ULift <| Fin n)) by
    apply Trunc.bind (this (Fintype.card α))
    intro h
    apply Trunc.map _ (Fintype.truncEquivFin α)
    intro e
    exact of_equiv (Equiv.ulift.trans e.symm) h
  apply ind where
    -- porting note: do a manual recursion, instead of `induction` tactic,
    -- to ensure the result is computable
    /-- Internal induction hypothesis -/
    ind : ∀ n : ℕ, Trunc (P (ULift <| Fin n))
    | Nat.zero => by
          have : card PEmpty = card (ULift (Fin 0)) := by simp only [card_fin, card_pempty,
                                                                     card_ulift]
          

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
P : Type u → Sort v
of_equiv : {α β : Type u} → α ≃ β → P α → P β
h_empty : P PEmpty.{u + 1}
h_option : {α : Type u} → [inst : Fintype α] → [inst : DecidableEq α] → P α → P (Option α)
α : Type u
inst✝¹ : Fintype α
inst✝ : DecidableEq α
this : card PEmpty.{?u.5312 + 1} = card (ULift.{?u.5322, 0} (Fin 0))
⊢ Trunc (P (ULift.{u, 0} (Fin zero)))

Next tactic:
apply Trunc.bind (truncEquivOfCardEq this)
/-- A recursor principle for finite types, analogous to `Nat.rec`. It effectively says
that every `Fintype` is either `Empty` or `Option α`, up to an `Equiv`. -/
def truncRecEmptyOption {P : Type u → Sort v} (of_equiv : ∀ {α β}, α ≃ β → P α → P β)
    (h_empty : P PEmpty) (h_option : ∀ {α} [Fintype α] [DecidableEq α], P α → P (Option α))
    (α : Type u) [Fintype α] [DecidableEq α] : Trunc (P α) := by
  suffices ∀ n : ℕ, Trunc (P (ULift <| Fin n)) by
    apply Trunc.bind (this (Fintype.card α))
    intro h
    apply Trunc.map _ (Fintype.truncEquivFin α)
    intro e
    exact of_equiv (Equiv.ulift.trans e.symm) h
  apply ind where
    -- porting note: do a manual recursion, instead of `induction` tactic,
    -- to ensure the result is computable
    /-- Internal induction hypothesis -/
    ind : ∀ n : ℕ, Trunc (P (ULift <| Fin n))
    | Nat.zero => by
          have : card PEmpty = card (ULift (Fin 0)) := by simp only [card_fin, card_pempty,
                                                                     card_ulift]
          apply Trunc.bind (truncEquivOfCardEq this)
          

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
P : Type u → Sort v
of_equiv : {α β : Type u} → α ≃ β → P α → P β
h_empty : P PEmpty.{u + 1}
h_option : {α : Type u} → [inst : Fintype α] → [inst : DecidableEq α] → P α → P (Option α)
α : Type u
inst✝¹ : Fintype α
inst✝ : DecidableEq α
this : card PEmpty.{?u.5312 + 1} = card (ULift.{?u.5322, 0} (Fin 0))
⊢ PEmpty.{?u.5312 + 1} ≃ ULift.{?u.5322, 0} (Fin 0) → Trunc (P (ULift.{u, 0} (Fin zero)))

Next tactic:
intro e
/-- A recursor principle for finite types, analogous to `Nat.rec`. It effectively says
that every `Fintype` is either `Empty` or `Option α`, up to an `Equiv`. -/
def truncRecEmptyOption {P : Type u → Sort v} (of_equiv : ∀ {α β}, α ≃ β → P α → P β)
    (h_empty : P PEmpty) (h_option : ∀ {α} [Fintype α] [DecidableEq α], P α → P (Option α))
    (α : Type u) [Fintype α] [DecidableEq α] : Trunc (P α) := by
  suffices ∀ n : ℕ, Trunc (P (ULift <| Fin n)) by
    apply Trunc.bind (this (Fintype.card α))
    intro h
    apply Trunc.map _ (Fintype.truncEquivFin α)
    intro e
    exact of_equiv (Equiv.ulift.trans e.symm) h
  apply ind where
    -- porting note: do a manual recursion, instead of `induction` tactic,
    -- to ensure the result is computable
    /-- Internal induction hypothesis -/
    ind : ∀ n : ℕ, Trunc (P (ULift <| Fin n))
    | Nat.zero => by
          have : card PEmpty = card (ULift (Fin 0)) := by simp only [card_fin, card_pempty,
                                                                     card_ulift]
          apply Trunc.bind (truncEquivOfCardEq this)
          intro e
          

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
P : Type u → Sort v
of_equiv : {α β : Type u} → α ≃ β → P α → P β
h_empty : P PEmpty.{u + 1}
h_option : {α : Type u} → [inst : Fintype α] → [inst : DecidableEq α] → P α → P (Option α)
α : Type u
inst✝¹ : Fintype α
inst✝ : DecidableEq α
this : card PEmpty.{?u.5312 + 1} = card (ULift.{?u.5322, 0} (Fin 0))
e : PEmpty.{?u.5312 + 1} ≃ ULift.{?u.5322, 0} (Fin 0)
⊢ Trunc (P (ULift.{u, 0} (Fin zero)))

Next tactic:
apply Trunc.mk