Theorem: CategoryTheory.Limits.Concrete.to_product_injective_of_isLimit
File: Mathlib/CategoryTheory/Limits/ConcreteCategory.lean

tactic: let E := (forget C).mapCone D
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
⊢ Function.Injective fun x j => (forget C).map (D.π.app j) x

tactic: let hE : IsLimit E := isLimitOfPreserves _ hD
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
⊢ Function.Injective fun x j => (forget C).map (D.π.app j) x

tactic: let G := Types.limitCone.{w, v} (F ⋙ forget C)
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
⊢ Function.Injective fun x j => (forget C).map (D.π.app j) x

tactic: let hG := Types.limitConeIsLimit.{w, v} (F ⋙ forget C)
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
⊢ Function.Injective fun x j => (forget C).map (D.π.app j) x

tactic: let T : E.pt ≅ G.pt := hE.conePointUniqueUpToIso hG
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
⊢ Function.Injective fun x j => (forget C).map (D.π.app j) x

tactic: change Function.Injective (T.hom ≫ fun x j => G.π.app j x)
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
⊢ Function.Injective fun x j => (forget C).map (D.π.app j) x

tactic: have h : Function.Injective T.hom := by
  intro a b h
  suffices T.inv (T.hom a) = T.inv (T.hom b) by simpa
  rw [h]
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
⊢ Function.Injective (T.hom ≫ fun x j => G.π.app j x)

tactic: suffices Function.Injective fun (x : G.pt) j => G.π.app j x by exact this.comp h
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
h : Function.Injective T.hom
⊢ Function.Injective (T.hom ≫ fun x j => G.π.app j x)

tactic: apply Subtype.ext
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
h : Function.Injective T.hom
⊢ Function.Injective fun x j => G.π.app j x

tactic: intro a b h
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
⊢ Function.Injective T.hom

tactic: suffices T.inv (T.hom a) = T.inv (T.hom b) by simpa
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
a b : E.pt
h : T.hom a = T.hom b
⊢ a = b

tactic: rw [h]
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
a b : E.pt
h : T.hom a = T.hom b
⊢ T.inv (T.hom a) = T.inv (T.hom b)

tactic: simpa
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
a b : E.pt
h : T.hom a = T.hom b
this : T.inv (T.hom a) = T.inv (T.hom b)
⊢ a = b

tactic: exact this.comp h
state_before: C : Type u
inst✝³ : Category C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : SmallCategory J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
E : Cone (F ⋙ forget C) := (forget C).mapCone D
hE : IsLimit E := isLimitOfPreserves (forget C) hD
G : Cone (F ⋙ forget C) := Types.limitCone (F ⋙ forget C)
hG : IsLimit (Types.limitCone (F ⋙ forget C)) := Types.limitConeIsLimit (F ⋙ forget C)
T : E.pt ≅ G.pt := IsLimit.conePointUniqueUpToIso hE hG
h : Function.Injective T.hom
this : Function.Injective fun x j => G.π.app j x
⊢ Function.Injective (T.hom ≫ fun x j => G.π.app j x)