Theorem: CategoryTheory.equiv_punit_iff_unique
File: Mathlib/CategoryTheory/PUnit.lean

tactic: constructor
state_before: C : Type u
inst✝ : Category.{v, u} C
⊢ Nonempty (C ≌ Discrete PUnit.{w + 1}) ↔ Nonempty C ∧ ∀ (x y : C), Nonempty (Unique (x ⟶ y))
state_after: case mp
C : Type u
inst✝ : Category.{v, u} C
⊢ Nonempty (C ≌ Discrete PUnit.{w + 1}) → Nonempty C ∧ ∀ (x y : C), Nonempty (Unique (x ⟶ y))

case mpr
C : Type u
inst✝ : Category.{v, u} C
⊢ (Nonempty C ∧ ∀ (x y : C), Nonempty (Unique (x ⟶ y))) → Nonempty (C ≌ Discrete PUnit.{w + 1})

tactic: rintro ⟨h⟩
state_before: case mp
C : Type u
inst✝ : Category.{v, u} C
⊢ Nonempty (C ≌ Discrete PUnit.{w + 1}) → Nonempty C ∧ ∀ (x y : C), Nonempty (Unique (x ⟶ y))
state_after: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
⊢ Nonempty C ∧ ∀ (x y : C), Nonempty (Unique (x ⟶ y))

tactic: refine ⟨⟨h.inverse.obj ⟨⟨⟩⟩⟩, fun x y => Nonempty.intro ?_⟩
state_before: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
⊢ Nonempty C ∧ ∀ (x y : C), Nonempty (Unique (x ⟶ y))
state_after: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
⊢ Unique (x ⟶ y)

tactic: let f : x ⟶ y := by
  have hx : x ⟶ h.inverse.obj ⟨⟨⟩⟩ := by convert h.unit.app x
  have hy : h.inverse.obj ⟨⟨⟩⟩ ⟶ y := by convert h.unitInv.app y
  exact hx ≫ hy
state_before: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
⊢ Unique (x ⟶ y)
state_after: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
⊢ Unique (x ⟶ y)

tactic: suffices sub : Subsingleton (x ⟶ y) from uniqueOfSubsingleton f
state_before: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
⊢ Unique (x ⟶ y)
state_after: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
⊢ Subsingleton (x ⟶ y)

tactic: apply Subsingleton.intro
state_before: case mp.intro
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
⊢ Subsingleton (x ⟶ y)
state_after: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
⊢ ∀ (a b : x ⟶ y), a = b

tactic: intro a b
state_before: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
⊢ ∀ (a b : x ⟶ y), a = b
state_after: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ a = b

tactic: rw [this a, this b]
state_before: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ a = b
state_after: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ h.unit.app x ≫ (h.functor ⋙ h.inverse).map a ≫ h.unitInv.app y =
    h.unit.app x ≫ (h.functor ⋙ h.inverse).map b ≫ h.unitInv.app y

tactic: simp only [Functor.comp_map]
state_before: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ h.unit.app x ≫ (h.functor ⋙ h.inverse).map a ≫ h.unitInv.app y =
    h.unit.app x ≫ (h.functor ⋙ h.inverse).map b ≫ h.unitInv.app y
state_after: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ h.unit.app x ≫ h.inverse.map (h.functor.map a) ≫ h.unitInv.app y =
    h.unit.app x ≫ h.inverse.map (h.functor.map b) ≫ h.unitInv.app y

tactic: congr 3
state_before: case mp.intro.allEq
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ h.unit.app x ≫ h.inverse.map (h.functor.map a) ≫ h.unitInv.app y =
    h.unit.app x ≫ h.inverse.map (h.functor.map b) ≫ h.unitInv.app y
state_after: case mp.intro.allEq.e_a.e_a.e_a
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ h.functor.map a = h.functor.map b

tactic: apply ULift.ext
state_before: case mp.intro.allEq.e_a.e_a.e_a
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ h.functor.map a = h.functor.map b
state_after: case mp.intro.allEq.e_a.e_a.e_a.h
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ (h.functor.map a).down = (h.functor.map b).down

tactic: simp [eq_iff_true_of_subsingleton]
state_before: case mp.intro.allEq.e_a.e_a.e_a.h
C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
this : ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
a b : x ⟶ y
⊢ (h.functor.map a).down = (h.functor.map b).down
state_after: no goals

tactic: have hx : x ⟶ h.inverse.obj ⟨⟨⟩⟩ := by convert h.unit.app x
state_before: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
⊢ x ⟶ y
state_after: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
hx : x ⟶ h.inverse.obj { as := PUnit.unit }
⊢ x ⟶ y

tactic: have hy : h.inverse.obj ⟨⟨⟩⟩ ⟶ y := by convert h.unitInv.app y
state_before: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
hx : x ⟶ h.inverse.obj { as := PUnit.unit }
⊢ x ⟶ y
state_after: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
hx : x ⟶ h.inverse.obj { as := PUnit.unit }
hy : h.inverse.obj { as := PUnit.unit } ⟶ y
⊢ x ⟶ y

tactic: exact hx ≫ hy
state_before: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
hx : x ⟶ h.inverse.obj { as := PUnit.unit }
hy : h.inverse.obj { as := PUnit.unit } ⟶ y
⊢ x ⟶ y
state_after: no goals

tactic: convert h.unit.app x
state_before: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
⊢ x ⟶ h.inverse.obj { as := PUnit.unit }
state_after: no goals

tactic: convert h.unitInv.app y
state_before: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
hx : x ⟶ h.inverse.obj { as := PUnit.unit }
⊢ h.inverse.obj { as := PUnit.unit } ⟶ y
state_after: no goals

tactic: intro z
state_before: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
⊢ ∀ (z : x ⟶ y), z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y
state_after: C : Type u
inst✝ : Category.{v, u} C
h : C ≌ Discrete PUnit.{w + 1}
x y : C
f : x ⟶ y :=
  let_fun hx := ⋯.mpr (id (h.unit.app x));
  let_fun hy := ⋯.mpr (id (h.unitInv.app y));
  hx ≫ hy
z : x ⟶ y
⊢ z = h.unit.app x ≫ (h.functor ⋙ h.inverse).map z ≫ h.unitInv.app y

tactic: rintro ⟨⟨p⟩, h⟩
state_before: case mpr
C : Type u
inst✝ : Category.{v, u} C
⊢ (Nonempty C ∧ ∀ (x y : C), Nonempty (Unique (x ⟶ y))) → Nonempty (C ≌ Discrete PUnit.{w + 1})
state_after: case mpr.intro.intro
C : Type u
inst✝ : Category.{v, u} C
h : ∀ (x y : C), Nonempty (Unique (x ⟶ y))
p : C
⊢ Nonempty (C ≌ Discrete PUnit.{w + 1})

tactic: haveI := fun x y => (h x y).some
state_before: case mpr.intro.intro
C : Type u
inst✝ : Category.{v, u} C
h : ∀ (x y : C), Nonempty (Unique (x ⟶ y))
p : C
⊢ Nonempty (C ≌ Discrete PUnit.{w + 1})
state_after: case mpr.intro.intro
C : Type u
inst✝ : Category.{v, u} C
h : ∀ (x y : C), Nonempty (Unique (x ⟶ y))
p : C
this : (x y : C) → Unique (x ⟶ y)
⊢ Nonempty (C ≌ Discrete PUnit.{w + 1})

tactic: refine
  Nonempty.intro
    (CategoryTheory.Equivalence.mk ((Functor.const _).obj ⟨⟨⟩⟩)
      ((@Functor.const <| Discrete PUnit).obj p) ?_ (by apply Functor.punitExt))
state_before: case mpr.intro.intro
C : Type u
inst✝ : Category.{v, u} C
h : ∀ (x y : C), Nonempty (Unique (x ⟶ y))
p : C
this : (x y : C) → Unique (x ⟶ y)
⊢ Nonempty (C ≌ Discrete PUnit.{w + 1})
state_after: case mpr.intro.intro
C : Type u
inst✝ : Category.{v, u} C
h : ∀ (x y : C), Nonempty (Unique (x ⟶ y))
p : C
this : (x y : C) → Unique (x ⟶ y)
⊢ 𝟭 C ≅ (Functor.const C).obj { as := PUnit.unit } ⋙ (Functor.const (Discrete PUnit.{w + 1})).obj p

tactic: exact
  NatIso.ofComponents fun _ =>
    { hom := default
      inv := default }
state_before: case mpr.intro.intro
C : Type u
inst✝ : Category.{v, u} C
h : ∀ (x y : C), Nonempty (Unique (x ⟶ y))
p : C
this : (x y : C) → Unique (x ⟶ y)
⊢ 𝟭 C ≅ (Functor.const C).obj { as := PUnit.unit } ⋙ (Functor.const (Discrete PUnit.{w + 1})).obj p
state_after: no goals

tactic: apply Functor.punitExt
state_before: C : Type u
inst✝ : Category.{v, u} C
h : ∀ (x y : C), Nonempty (Unique (x ⟶ y))
p : C
this : (x y : C) → Unique (x ⟶ y)
⊢ (Functor.const (Discrete PUnit.{w + 1})).obj p ⋙ (Functor.const C).obj { as := PUnit.unit } ≅
    𝟭 (Discrete PUnit.{w + 1})
state_after: no goals