-- Mathlib/CategoryTheory/Preadditive/Injective/Basic.lean
theorem injective_of_map_injective (adj : F ⊣ G) [G.Full] [G.Faithful] (I : D)
    (hI : Injective (G.obj I)) : Injective I :=
  ⟨fun {X} {Y} f g => by
    intro
    haveI : PreservesLimitsOfSize.{0, 0} G := adj.rightAdjoint_preservesLimits
    rcases hI.factors (G.map f) (G.map g) with ⟨w,h⟩
    use inv (adj.counit.app _) ≫ F.map w ≫ adj.counit.app _
    exact G.map_injective (by simpa)⟩

Proof state:
case h
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
this : PreservesLimitsOfSize.{0, 0, u_2, v₁, u_1, u₁} G
w : G.obj Y ⟶ G.obj I
h : G.map g ≫ w = G.map f
⊢ g ≫ inv (adj.counit.app Y) ≫ F.map w ≫ adj.counit.app I = f

Tactic:
exact G.map_injective (by simpa)

Result:
no goals

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
this : PreservesLimitsOfSize.{0, 0, u_2, v₁, u_1, u₁} G
⊢ ∃ h, g ≫ h = f

Tactic:
rcases hI.factors (G.map f) (G.map g) with ⟨w,h⟩

Result:
case intro
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
this : PreservesLimitsOfSize.{0, 0, u_2, v₁, u_1, u₁} G
w : G.obj Y ⟶ G.obj I
h : G.map g ≫ w = G.map f
⊢ ∃ h, g ≫ h = f

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
this : PreservesLimitsOfSize.{0, 0, u_2, v₁, u_1, u₁} G
w : G.obj Y ⟶ G.obj I
h : G.map g ≫ w = G.map f
⊢ G.map (g ≫ inv (adj.counit.app Y) ≫ F.map w ≫ adj.counit.app I) = G.map f

Tactic:
simpa

Result:
no goals

Proof state:
case intro
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
this : PreservesLimitsOfSize.{0, 0, u_2, v₁, u_1, u₁} G
w : G.obj Y ⟶ G.obj I
h : G.map g ≫ w = G.map f
⊢ ∃ h, g ≫ h = f

Tactic:
use inv (adj.counit.app _) ≫ F.map w ≫ adj.counit.app _

Result:
case h
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
this : PreservesLimitsOfSize.{0, 0, u_2, v₁, u_1, u₁} G
w : G.obj Y ⟶ G.obj I
h : G.map g ≫ w = G.map f
⊢ g ≫ inv (adj.counit.app Y) ≫ F.map w ≫ adj.counit.app I = f

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u_1
inst✝² : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝¹ : G.Full
inst✝ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
⊢ ∀ [inst : Mono g], ∃ h, g ≫ h = f

Tactic:
intro

Result:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
⊢ ∃ h, g ≫ h = f

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
⊢ ∃ h, g ≫ h = f

Tactic:
haveI : PreservesLimitsOfSize.{0, 0} G := adj.rightAdjoint_preservesLimits

Result:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u_1
inst✝³ : Category.{u_2, u_1} D
F : C ⥤ D
G : D ⥤ C
adj : F ⊣ G
inst✝² : G.Full
inst✝¹ : G.Faithful
I : D
hI : Injective (G.obj I)
X Y : D
f : X ⟶ I
g : X ⟶ Y
inst✝ : Mono g
this : PreservesLimitsOfSize.{0, 0, u_2, v₁, u_1, u₁} G
⊢ ∃ h, g ≫ h = f