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

Proof steps:
state_before: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} J
F : J ⥤ C
inst✝ : PreservesLimit F (forget C)
D : Cone F
hD : IsLimit D
⊢ Function.Injective fun x j => (D.π.app j) x
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
tactic: let E := (forget C).mapCone D
state_before: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
tactic: let hE : IsLimit E := isLimitOfPreserves _ hD
state_before: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
tactic: let G := Types.limitCone.{w, v} (F ⋙ forget C)
state_before: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
tactic: let hG := Types.limitConeIsLimit.{w, v} (F ⋙ forget C)
state_before: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 => (D.π.app j) x
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
⊢ Function.Injective fun x j => (D.π.app j) x
tactic: let T : E.pt ≅ G.pt := hE.conePointUniqueUpToIso hG
state_before: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
⊢ Function.Injective fun x j => (D.π.app j) x
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
⊢ Function.Injective (T.hom ≫ fun x j => G.π.app j x)
tactic: change Function.Injective (T.hom ≫ fun x j => G.π.app j x)
state_before: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
⊢ Function.Injective (T.hom ≫ fun x j => G.π.app j x)
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
h : Function.Injective T.hom
⊢ Function.Injective (T.hom ≫ fun x j => G.π.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.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
h : Function.Injective T.hom
⊢ Function.Injective (T.hom ≫ fun x j => G.π.app j x)
state_after: C : Type u
inst✝³ : Category.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
h : Function.Injective T.hom
⊢ Function.Injective 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.{v, u} C
inst✝² : ConcreteCategory C
J : Type w
inst✝¹ : Category.{t, w} 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 := hE.conePointUniqueUpToIso hG
h : Function.Injective T.hom
⊢ Function.Injective fun x j => G.π.app j x
state_after: no goals
tactic: apply Subtype.ext