File: Mathlib/CategoryTheory/DiscreteCategory.lean

full_name: CategoryTheory.Discrete
code: /-- A wrapper for promoting any type to a category,
with the only morphisms being equalities.
-/
@[ext, aesop safe cases (rule_sets := [CategoryTheory])]
structure Discrete (α : Type u₁) where
  /-- A wrapper for promoting any type to a category,
  with the only morphisms being equalities. -/
  as : α
goal: Type u₁

full_name: CategoryTheory.Discrete.as
code: /-- A wrapper for promoting any type to a category,
with the only morphisms being equalities.
-/
@[ext, aesop safe cases (rule_sets := [CategoryTheory])]
structure Discrete (α : Type u₁) where
  /-- A wrapper for promoting any type to a category,
  with the only morphisms being equalities. -/
  as : α
goal: α

full_name: CategoryTheory.Discrete.mk_as
code: @[simp]
theorem Discrete.mk_as {α : Type u₁} (X : Discrete α) : Discrete.mk X.as = X 
goal: { as := X.as } = X

full_name: CategoryTheory.discreteEquiv
code: /-- `Discrete α` is equivalent to the original type `α`. -/
@[simps]
def discreteEquiv {α : Type u₁} : Discrete α ≃ α 
goal: CategoryTheory.Discrete α ≃ α

full_name: CategoryTheory.discreteEquiv_symm_apply_as
code: /-- `Discrete α` is equivalent to the original type `α`. -/
@[simps]
def discreteEquiv {α : Type u₁} : Discrete α ≃ α 
goal: (CategoryTheory.discreteEquiv.symm as).as = as

full_name: CategoryTheory.discreteEquiv_apply
code: /-- `Discrete α` is equivalent to the original type `α`. -/
@[simps]
def discreteEquiv {α : Type u₁} : Discrete α ≃ α 
goal: CategoryTheory.discreteEquiv self = self.as

full_name: CategoryTheory.instDecidableEqDiscrete
code: instance {α : Type u₁} [DecidableEq α] : DecidableEq (Discrete α) 
goal: DecidableEq (CategoryTheory.Discrete α)

full_name: CategoryTheory.discreteCategory
code: /-- The "Discrete" category on a type, whose morphisms are equalities.

Because we do not allow morphisms in `Prop` (only in `Type`),
somewhat annoyingly we have to define `X ⟶ Y` as `ULift (PLift (X = Y))`.

See <https://stacks.math.columbia.edu/tag/001A>
-/
instance discreteCategory (α : Type u₁) : SmallCategory (Discrete α) 
goal: CategoryTheory.SmallCategory (CategoryTheory.Discrete α)

full_name: CategoryTheory.Discrete.instInhabited
code: instance [Inhabited α] : Inhabited (Discrete α) 
goal: Inhabited (CategoryTheory.Discrete α)

full_name: CategoryTheory.Discrete.instSubsingleton
code: instance [Subsingleton α] : Subsingleton (Discrete α) 
goal: Subsingleton (CategoryTheory.Discrete α)

full_name: CategoryTheory.Discrete.instSubsingletonDiscreteHom
code: instance instSubsingletonDiscreteHom (X Y : Discrete α) : Subsingleton (X ⟶ Y) 
goal: Subsingleton (X ⟶ Y)

full_name: CategoryTheory.Discrete._aux_Mathlib_CategoryTheory_DiscreteCategory___macroRules_CategoryTheory_Discrete_tacticDiscrete_cases_1
code: macro "discrete_cases" : tactic =>
  `(tactic| fail_if_no_progress casesm* Discrete _, (_ : Discrete _) ⟶ (_ : Discrete _), PLift _)
goal: Lean.Macro

full_name: CategoryTheory.Discrete.tacticDiscrete_cases
code: macro "discrete_cases" : tactic =>
  `(tactic| fail_if_no_progress casesm* Discrete _, (_ : Discrete _) ⟶ (_ : Discrete _), PLift _)
goal: Lean.ParserDescr

full_name: CategoryTheory.Discrete.discreteCases
code: /--
Use:
```
attribute [local aesop safe tactic (rule_sets := [CategoryTheory])]
  CategoryTheory.Discrete.discreteCases
```
to locally gives `aesop_cat` the ability to call `cases` on
`Discrete` and `(_ : Discrete _) ⟶ (_ : Discrete _)` hypotheses.
-/
def discreteCases : TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: CategoryTheory.Discrete.instUnique
code: instance [Unique α] : Unique (Discrete α) 
goal: Unique (CategoryTheory.Discrete α)

full_name: CategoryTheory.Discrete.eq_of_hom
code: /-- Extract the equation from a morphism in a discrete category. -/
theorem eq_of_hom {X Y : Discrete α} (i : X ⟶ Y) : X.as = Y.as 
goal: X.as = Y.as

full_name: CategoryTheory.Discrete.eqToHom
code: /-- Promote an equation between the wrapped terms in `X Y : Discrete α` to a morphism `X ⟶ Y`
in the discrete category. -/
protected abbrev eqToHom {X Y : Discrete α} (h : X.as = Y.as) : X ⟶ Y 
goal: X ⟶ Y

full_name: CategoryTheory.Discrete.eqToIso
code: /-- Promote an equation between the wrapped terms in `X Y : Discrete α` to an isomorphism `X ≅ Y`
in the discrete category. -/
protected abbrev eqToIso {X Y : Discrete α} (h : X.as = Y.as) : X ≅ Y 
goal: X ≅ Y

full_name: CategoryTheory.Discrete.eqToHom'
code: /-- A variant of `eqToHom` that lifts terms to the discrete category. -/
abbrev eqToHom' {a b : α} (h : a = b) : Discrete.mk a ⟶ Discrete.mk b 
goal: { as := a } ⟶ { as := b }

full_name: CategoryTheory.Discrete.eqToIso'
code: /-- A variant of `eqToIso` that lifts terms to the discrete category. -/
abbrev eqToIso' {a b : α} (h : a = b) : Discrete.mk a ≅ Discrete.mk b 
goal: { as := a } ≅ { as := b }

full_name: CategoryTheory.Discrete.id_def
code: @[simp]
theorem id_def (X : Discrete α) : ULift.up (PLift.up (Eq.refl X.as)) = 𝟙 X 
goal: { down := { down := ⋯ } } = CategoryTheory.CategoryStruct.id X

full_name: CategoryTheory.Discrete.instIsIso
code: instance {I : Type u₁} {i j : Discrete I} (f : i ⟶ j) : IsIso f 
goal: CategoryTheory.IsIso f

full_name: CategoryTheory.Discrete.functor
code: /-- Any function `I → C` gives a functor `Discrete I ⥤ C`. -/
def functor {I : Type u₁} (F : I → C) : Discrete I ⥤ C 
goal: CategoryTheory.Functor (CategoryTheory.Discrete I) C

full_name: CategoryTheory.Discrete.functor_obj
code: @[simp]
theorem functor_obj {I : Type u₁} (F : I → C) (i : I) :
    (Discrete.functor F).obj (Discrete.mk i) = F i 
goal: (CategoryTheory.Discrete.functor F).obj { as := i } = F i

full_name: CategoryTheory.Discrete.functor_map
code: @[simp]
theorem functor_map {I : Type u₁} (F : I → C) {i : Discrete I} (f : i ⟶ i) :
    (Discrete.functor F).map f = 𝟙 (F i.as) 
goal: (CategoryTheory.Discrete.functor F).map f = CategoryTheory.CategoryStruct.id (F i.as)

full_name: CategoryTheory.Discrete.functor_obj_eq_as
code: @[simp]
theorem functor_obj_eq_as {I : Type u₁} (F : I → C) (X : Discrete I) :
    (Discrete.functor F).obj X = F X.as 
goal: (CategoryTheory.Discrete.functor F).obj X = F X.as

full_name: CategoryTheory.Discrete.functorComp_hom_app
code: /-- The discrete functor induced by a composition of maps can be written as a
composition of two discrete functors.
-/
@[simps!]
def functorComp {I : Type u₁} {J : Type u₁'} (f : J → C) (g : I → J) :
    Discrete.functor (f ∘ g) ≅ Discrete.functor (Discrete.mk ∘ g) ⋙ Discrete.functor f 
goal: (CategoryTheory.Discrete.functorComp f g).hom.app X = CategoryTheory.CategoryStruct.id (f (g X.as))

full_name: CategoryTheory.Discrete.functorComp
code: /-- The discrete functor induced by a composition of maps can be written as a
composition of two discrete functors.
-/
@[simps!]
def functorComp {I : Type u₁} {J : Type u₁'} (f : J → C) (g : I → J) :
    Discrete.functor (f ∘ g) ≅ Discrete.functor (Discrete.mk ∘ g) ⋙ Discrete.functor f 
goal: CategoryTheory.Discrete.functor (f ∘ g) ≅
  (CategoryTheory.Discrete.functor (CategoryTheory.Discrete.mk ∘ g)).comp (CategoryTheory.Discrete.functor f)

full_name: CategoryTheory.Discrete.functorComp_inv_app
code: /-- The discrete functor induced by a composition of maps can be written as a
composition of two discrete functors.
-/
@[simps!]
def functorComp {I : Type u₁} {J : Type u₁'} (f : J → C) (g : I → J) :
    Discrete.functor (f ∘ g) ≅ Discrete.functor (Discrete.mk ∘ g) ⋙ Discrete.functor f 
goal: (CategoryTheory.Discrete.functorComp f g).inv.app X = CategoryTheory.CategoryStruct.id (f (g X.as))

full_name: CategoryTheory.Discrete.natTrans
code: /-- For functors out of a discrete category,
a natural transformation is just a collection of maps,
as the naturality squares are trivial.
-/
@[simps]
def natTrans {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ⟶ G.obj i) :
    F ⟶ G 
goal: F ⟶ G

full_name: CategoryTheory.Discrete.natTrans_app
code: /-- For functors out of a discrete category,
a natural transformation is just a collection of maps,
as the naturality squares are trivial.
-/
@[simps]
def natTrans {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ⟶ G.obj i) :
    F ⟶ G 
goal: (CategoryTheory.Discrete.natTrans f).app i = f i

full_name: CategoryTheory.Discrete.natIso_inv_app
code: /-- For functors out of a discrete category,
a natural isomorphism is just a collection of isomorphisms,
as the naturality squares are trivial.
-/
@[simps!]
def natIso {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i) :
    F ≅ G 
goal: (CategoryTheory.Discrete.natIso f).inv.app X = (f X).inv

full_name: CategoryTheory.Discrete.natIso_hom_app
code: /-- For functors out of a discrete category,
a natural isomorphism is just a collection of isomorphisms,
as the naturality squares are trivial.
-/
@[simps!]
def natIso {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i) :
    F ≅ G 
goal: (CategoryTheory.Discrete.natIso f).hom.app X = (f X).hom

full_name: CategoryTheory.Discrete.natIso
code: /-- For functors out of a discrete category,
a natural isomorphism is just a collection of isomorphisms,
as the naturality squares are trivial.
-/
@[simps!]
def natIso {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i) :
    F ≅ G 
goal: F ≅ G

full_name: CategoryTheory.Discrete.instIsIsoFunctorNatTrans
code: instance {I : Type*} {F G : Discrete I ⥤ C} (f : ∀ i, F.obj i ⟶ G.obj i) [∀ i, IsIso (f i)] :
    IsIso (Discrete.natTrans f) 
goal: CategoryTheory.IsIso (CategoryTheory.Discrete.natTrans f)

full_name: CategoryTheory.Discrete.natIso_app
code: @[simp]
theorem natIso_app {I : Type u₁} {F G : Discrete I ⥤ C} (f : ∀ i : Discrete I, F.obj i ≅ G.obj i)
    (i : Discrete I) : (Discrete.natIso f).app i = f i 
goal: (CategoryTheory.Discrete.natIso f).app i = f i

full_name: CategoryTheory.Discrete.natIsoFunctor
code: /-- Every functor `F` from a discrete category is naturally isomorphic (actually, equal) to
  `Discrete.functor (F.obj)`. -/
@[simp]
def natIsoFunctor {I : Type u₁} {F : Discrete I ⥤ C} : F ≅ Discrete.functor (F.obj ∘ Discrete.mk) 
goal: F ≅ CategoryTheory.Discrete.functor (F.obj ∘ CategoryTheory.Discrete.mk)

full_name: CategoryTheory.Discrete.compNatIsoDiscrete
code: /-- Composing `Discrete.functor F` with another functor `G` amounts to composing `F` with `G.obj` -/
@[simp]
def compNatIsoDiscrete {I : Type u₁} {D : Type u₃} [Category.{v₃} D] (F : I → C) (G : C ⥤ D) :
    Discrete.functor F ⋙ G ≅ Discrete.functor (G.obj ∘ F) 
goal: (CategoryTheory.Discrete.functor F).comp G ≅ CategoryTheory.Discrete.functor (G.obj ∘ F)

full_name: CategoryTheory.Discrete.equivalence_functor
code: /-- We can promote a type-level `Equiv` to
an equivalence between the corresponding `discrete` categories.
-/
@[simps]
def equivalence {I : Type u₁} {J : Type u₂} (e : I ≃ J) : Discrete I ≌ Discrete J 
goal: (CategoryTheory.Discrete.equivalence e).functor = CategoryTheory.Discrete.functor (CategoryTheory.Discrete.mk ∘ ⇑e)

full_name: CategoryTheory.Discrete.equivalence_counitIso
code: /-- We can promote a type-level `Equiv` to
an equivalence between the corresponding `discrete` categories.
-/
@[simps]
def equivalence {I : Type u₁} {J : Type u₂} (e : I ≃ J) : Discrete I ≌ Discrete J 
goal: (CategoryTheory.Discrete.equivalence e).counitIso = CategoryTheory.Discrete.natIso fun j => CategoryTheory.eqToIso ⋯

full_name: CategoryTheory.Discrete.equivalence
code: /-- We can promote a type-level `Equiv` to
an equivalence between the corresponding `discrete` categories.
-/
@[simps]
def equivalence {I : Type u₁} {J : Type u₂} (e : I ≃ J) : Discrete I ≌ Discrete J 
goal: CategoryTheory.Discrete I ≌ CategoryTheory.Discrete J

full_name: CategoryTheory.Discrete.equivalence_unitIso
code: /-- We can promote a type-level `Equiv` to
an equivalence between the corresponding `discrete` categories.
-/
@[simps]
def equivalence {I : Type u₁} {J : Type u₂} (e : I ≃ J) : Discrete I ≌ Discrete J 
goal: (CategoryTheory.Discrete.equivalence e).unitIso = CategoryTheory.Discrete.natIso fun i => CategoryTheory.eqToIso ⋯

full_name: CategoryTheory.Discrete.equivalence_inverse
code: /-- We can promote a type-level `Equiv` to
an equivalence between the corresponding `discrete` categories.
-/
@[simps]
def equivalence {I : Type u₁} {J : Type u₂} (e : I ≃ J) : Discrete I ≌ Discrete J 
goal: (CategoryTheory.Discrete.equivalence e).inverse = CategoryTheory.Discrete.functor (CategoryTheory.Discrete.mk ∘ ⇑e.symm)

full_name: CategoryTheory.Discrete.equivOfEquivalence_symm_apply
code: /-- We can convert an equivalence of `discrete` categories to a type-level `Equiv`. -/
@[simps]
def equivOfEquivalence {α : Type u₁} {β : Type u₂} (h : Discrete α ≌ Discrete β) : α ≃ β 
goal: ∀ (a : β),
  (CategoryTheory.Discrete.equivOfEquivalence h).symm a =
    (CategoryTheory.Discrete.as ∘ h.inverse.obj ∘ CategoryTheory.Discrete.mk) a

full_name: CategoryTheory.Discrete.equivOfEquivalence
code: /-- We can convert an equivalence of `discrete` categories to a type-level `Equiv`. -/
@[simps]
def equivOfEquivalence {α : Type u₁} {β : Type u₂} (h : Discrete α ≌ Discrete β) : α ≃ β 
goal: α ≃ β

full_name: CategoryTheory.Discrete.equivOfEquivalence_apply
code: /-- We can convert an equivalence of `discrete` categories to a type-level `Equiv`. -/
@[simps]
def equivOfEquivalence {α : Type u₁} {β : Type u₂} (h : Discrete α ≌ Discrete β) : α ≃ β 
goal: ∀ (a : α),
  (CategoryTheory.Discrete.equivOfEquivalence h) a =
    (CategoryTheory.Discrete.as ∘ h.functor.obj ∘ CategoryTheory.Discrete.mk) a

full_name: CategoryTheory.Discrete.opposite_inverse_obj
code: /-- A discrete category is equivalent to its opposite category. -/
@[simps! functor_obj_as inverse_obj]
protected def opposite (α : Type u₁) : (Discrete α)ᵒᵖ ≌ Discrete α 
goal: ∀ (a : CategoryTheory.Discrete α), (CategoryTheory.Discrete.opposite α).inverse.obj a = Opposite.op a

full_name: CategoryTheory.Discrete.opposite_functor_obj_as
code: /-- A discrete category is equivalent to its opposite category. -/
@[simps! functor_obj_as inverse_obj]
protected def opposite (α : Type u₁) : (Discrete α)ᵒᵖ ≌ Discrete α 
goal: ((CategoryTheory.Discrete.opposite α).functor.obj X).as = (Opposite.unop X).as

full_name: CategoryTheory.Discrete.opposite
code: /-- A discrete category is equivalent to its opposite category. -/
@[simps! functor_obj_as inverse_obj]
protected def opposite (α : Type u₁) : (Discrete α)ᵒᵖ ≌ Discrete α 
goal: (CategoryTheory.Discrete α)ᵒᵖ ≌ CategoryTheory.Discrete α

full_name: CategoryTheory.Discrete.functor_map_id
code: @[simp]
theorem functor_map_id (F : Discrete J ⥤ C) {j : Discrete J} (f : j ⟶ j) :
    F.map f = 𝟙 (F.obj j) 
goal: F.map f = CategoryTheory.CategoryStruct.id (F.obj j)

full_name: CategoryTheory.piEquivalenceFunctorDiscrete_counitIso
code: /-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
@[simps]
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) 
goal: (CategoryTheory.piEquivalenceFunctorDiscrete J C).counitIso =
  CategoryTheory.NatIso.ofComponents
    (fun F =>
      CategoryTheory.NatIso.ofComponents
        (fun j =>
          CategoryTheory.Iso.refl
            ((({ obj := fun F j => F.obj { as := j }, map := fun {X Y} f j => f.app { as := j }, map_id := ⋯,
                          map_comp := ⋯ }.comp
                      { obj := fun F => CategoryTheory.Discrete.functor F,
                        map := fun {X Y} f => CategoryTheory.Discrete.natTrans fun j => f j.as, map_id := ⋯,
                        map_comp := ⋯ }).obj
                  F).obj
              j))
        ⋯)
    ⋯

full_name: CategoryTheory.piEquivalenceFunctorDiscrete_inverse_map
code: /-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
@[simps]
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) 
goal: ∀ {X Y : CategoryTheory.Functor (CategoryTheory.Discrete J) C} (f : X ⟶ Y) (j : J),
  (CategoryTheory.piEquivalenceFunctorDiscrete J C).inverse.map f j = f.app { as := j }

full_name: CategoryTheory.piEquivalenceFunctorDiscrete_functor_map
code: /-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
@[simps]
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) 
goal: ∀ {X Y : J → C} (f : X ⟶ Y),
  (CategoryTheory.piEquivalenceFunctorDiscrete J C).functor.map f = CategoryTheory.Discrete.natTrans fun j => f j.as

full_name: CategoryTheory.piEquivalenceFunctorDiscrete_unitIso
code: /-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
@[simps]
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) 
goal: (CategoryTheory.piEquivalenceFunctorDiscrete J C).unitIso = CategoryTheory.Iso.refl (CategoryTheory.Functor.id (J → C))

full_name: CategoryTheory.piEquivalenceFunctorDiscrete
code: /-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
@[simps]
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) 
goal: J → C ≌ CategoryTheory.Functor (CategoryTheory.Discrete J) C

full_name: CategoryTheory.piEquivalenceFunctorDiscrete_inverse_obj
code: /-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
@[simps]
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) 
goal: (CategoryTheory.piEquivalenceFunctorDiscrete J C).inverse.obj F j = F.obj { as := j }

full_name: CategoryTheory.piEquivalenceFunctorDiscrete_functor_obj
code: /-- The equivalence of categories `(J → C) ≌ (Discrete J ⥤ C)`. -/
@[simps]
def piEquivalenceFunctorDiscrete (J : Type u₂) (C : Type u₁) [Category.{v₁} C] :
    (J → C) ≌ (Discrete J ⥤ C) 
goal: (CategoryTheory.piEquivalenceFunctorDiscrete J C).functor.obj F = CategoryTheory.Discrete.functor F