l3lab/ntp-mathlib huggingface dataset:
theorem NoZeroSMulDivisors.int_of_charZero [CharZero R] : NoZeroSMulDivisors ℤ M :=
  ⟨fun {z x} h ↦ by 

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝⁴ : Ring R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : NoZeroSMulDivisors R M
inst✝ : CharZero R
z : ℤ
x : M
h : z • x = 0
⊢ z = 0 ∨ x = 0

Next tactic:
simpa [← smul_one_smul R z x] using h
/-- Only a ring of characteristic zero can can have a non-trivial module without additive or
scalar torsion. -/
theorem CharZero.of_noZeroSMulDivisors [Nontrivial M] [NoZeroSMulDivisors ℤ M] : CharZero R := by
  

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝⁵ : Ring R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : NoZeroSMulDivisors R M
inst✝¹ : Nontrivial M
inst✝ : NoZeroSMulDivisors ℤ M
⊢ CharZero R

Next tactic:
refine ⟨fun {n m h} ↦ ?_⟩
/-- Only a ring of characteristic zero can can have a non-trivial module without additive or
scalar torsion. -/
theorem CharZero.of_noZeroSMulDivisors [Nontrivial M] [NoZeroSMulDivisors ℤ M] : CharZero R := by
  refine ⟨fun {n m h} ↦ ?_⟩
  

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝⁵ : Ring R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : NoZeroSMulDivisors R M
inst✝¹ : Nontrivial M
inst✝ : NoZeroSMulDivisors ℤ M
n m : ℕ
h : ↑n = ↑m
⊢ n = m

Next tactic:
obtain ⟨x, hx⟩ := exists_ne (0 : M)
/-- Only a ring of characteristic zero can can have a non-trivial module without additive or
scalar torsion. -/
theorem CharZero.of_noZeroSMulDivisors [Nontrivial M] [NoZeroSMulDivisors ℤ M] : CharZero R := by
  refine ⟨fun {n m h} ↦ ?_⟩
  obtain ⟨x, hx⟩ := exists_ne (0 : M)
  

Proof state:
case intro
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝⁵ : Ring R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : NoZeroSMulDivisors R M
inst✝¹ : Nontrivial M
inst✝ : NoZeroSMulDivisors ℤ M
n m : ℕ
h : ↑n = ↑m
x : M
hx : x ≠ 0
⊢ n = m

Next tactic:
replace h : (n : ℤ) • x = (m : ℤ) • x := by simp [zsmul_eq_smul_cast R, h]
/-- Only a ring of characteristic zero can can have a non-trivial module without additive or
scalar torsion. -/
theorem CharZero.of_noZeroSMulDivisors [Nontrivial M] [NoZeroSMulDivisors ℤ M] : CharZero R := by
  refine ⟨fun {n m h} ↦ ?_⟩
  obtain ⟨x, hx⟩ := exists_ne (0 : M)
  replace h : (n : ℤ) • x = (m : ℤ) • x := by 

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝⁵ : Ring R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : NoZeroSMulDivisors R M
inst✝¹ : Nontrivial M
inst✝ : NoZeroSMulDivisors ℤ M
n m : ℕ
h : ↑n = ↑m
x : M
hx : x ≠ 0
⊢ ↑n • x = ↑m • x

Next tactic:
simp [zsmul_eq_smul_cast R, h]
/-- Only a ring of characteristic zero can can have a non-trivial module without additive or
scalar torsion. -/
theorem CharZero.of_noZeroSMulDivisors [Nontrivial M] [NoZeroSMulDivisors ℤ M] : CharZero R := by
  refine ⟨fun {n m h} ↦ ?_⟩
  obtain ⟨x, hx⟩ := exists_ne (0 : M)
  replace h : (n : ℤ) • x = (m : ℤ) • x := by simp [zsmul_eq_smul_cast R, h]
  

Proof state:
case intro
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝⁵ : Ring R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : NoZeroSMulDivisors R M
inst✝¹ : Nontrivial M
inst✝ : NoZeroSMulDivisors ℤ M
n m : ℕ
x : M
hx : x ≠ 0
h : ↑n • x = ↑m • x
⊢ n = m

Next tactic:
simpa using smul_left_injective ℤ hx h
instance (priority := 100) RatModule.noZeroSMulDivisors [AddCommGroup M] [Module ℚ M] :
    NoZeroSMulDivisors ℤ M :=
  ⟨fun {k} {x : M} h => by
    

Proof state:
α : Type u_1
R : Type u_2
k✝ : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝¹ : AddCommGroup M
inst✝ : Module ℚ M
k : ℤ
x : M
h : k • x = 0
⊢ k = 0 ∨ x = 0

Next tactic:
simpa only [zsmul_eq_smul_cast ℚ k x, smul_eq_zero, Rat.zero_iff_num_zero] using h
theorem Nat.smul_one_eq_coe {R : Type*} [Semiring R] (m : ℕ) : m • (1 : R) = ↑m := by
  

Proof state:
α : Type u_1
R✝ : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
R : Type u_9
inst✝ : Semiring R
m : ℕ
⊢ m • 1 = ↑m

Next tactic:
rw [nsmul_eq_mul, mul_one]
theorem Int.smul_one_eq_coe {R : Type*} [Ring R] (m : ℤ) : m • (1 : R) = ↑m := by
  

Proof state:
α : Type u_1
R✝ : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
R : Type u_9
inst✝ : Ring R
m : ℤ
⊢ m • 1 = ↑m

Next tactic:
rw [zsmul_eq_mul, mul_one]
lemma support_smul_subset_left [Zero R] [Zero M] [SMulWithZero R M] (f : α → R) (g : α → M) :
    support (f • g) ⊆ support f := fun x hfg hf ↦ hfg $ by 

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulWithZero R M
f : α → R
g : α → M
x : α
hfg : x ∈ support (f • g)
hf : f x = 0
⊢ (f • g) x = 0

Next tactic:
rw [Pi.smul_apply', hf, zero_smul]
lemma support_const_smul_of_ne_zero [Zero R] [Zero M] [SMulWithZero R M] [NoZeroSMulDivisors R M]
    (c : R) (g : α → M) (hc : c ≠ 0) : support (c • g) = support g :=
  ext fun x ↦ by 

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝³ : Zero R
inst✝² : Zero M
inst✝¹ : SMulWithZero R M
inst✝ : NoZeroSMulDivisors R M
c : R
g : α → M
hc : c ≠ 0
x : α
⊢ x ∈ support (c • g) ↔ x ∈ support g

Next tactic:
simp only [hc, mem_support, Pi.smul_apply, Ne.def, smul_eq_zero, false_or_iff]
lemma support_smul_subset_right [Zero M] [SMulZeroClass R M] (a : R) (f : α → M) :
    support (a • f) ⊆ support f := fun x hbf hf =>
  hbf <| by 

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝¹ : Zero M
inst✝ : SMulZeroClass R M
a : R
f : α → M
x : α
hbf : x ∈ support (a • f)
hf : f x = 0
⊢ (a • f) x = 0

Next tactic:
rw [Pi.smul_apply, hf, smul_zero]
lemma indicator_smul_apply (s : Set α) (r : α → R) (f : α → M) (a : α) :
    indicator s (fun a ↦ r a • f a) a = r a • indicator s f a := by
  

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulZeroClass R M
s : Set α
r : α → R
f : α → M
a : α
⊢ indicator s (fun a => r a • f a) a = r a • indicator s f a

Next tactic:
dsimp only [indicator]
lemma indicator_smul_apply (s : Set α) (r : α → R) (f : α → M) (a : α) :
    indicator s (fun a ↦ r a • f a) a = r a • indicator s f a := by
  dsimp only [indicator]
  

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulZeroClass R M
s : Set α
r : α → R
f : α → M
a : α
⊢ (if a ∈ s then r a • f a else 0) = r a • if a ∈ s then f a else 0

Next tactic:
split_ifs
lemma indicator_smul_apply (s : Set α) (r : α → R) (f : α → M) (a : α) :
    indicator s (fun a ↦ r a • f a) a = r a • indicator s f a := by
  dsimp only [indicator]
  split_ifs
  

Proof state:
case pos
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulZeroClass R M
s : Set α
r : α → R
f : α → M
a : α
h✝ : a ∈ s
⊢ r a • f a = r a • f a
case neg
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulZeroClass R M
s : Set α
r : α → R
f : α → M
a : α
h✝ : a ∉ s
⊢ 0 = r a • 0

Next tactic:
exacts [rfl, (smul_zero (r a)).symm]
lemma indicator_smul_apply_left (s : Set α) (r : α → R) (f : α → M) (a : α) :
    indicator s (fun a ↦ r a • f a) a = indicator s r a • f a := by
  

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulWithZero R M
s : Set α
r : α → R
f : α → M
a : α
⊢ indicator s (fun a => r a • f a) a = indicator s r a • f a

Next tactic:
dsimp only [indicator]
lemma indicator_smul_apply_left (s : Set α) (r : α → R) (f : α → M) (a : α) :
    indicator s (fun a ↦ r a • f a) a = indicator s r a • f a := by
  dsimp only [indicator]
  

Proof state:
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulWithZero R M
s : Set α
r : α → R
f : α → M
a : α
⊢ (if a ∈ s then r a • f a else 0) = (if a ∈ s then r a else 0) • f a

Next tactic:
split_ifs
lemma indicator_smul_apply_left (s : Set α) (r : α → R) (f : α → M) (a : α) :
    indicator s (fun a ↦ r a • f a) a = indicator s r a • f a := by
  dsimp only [indicator]
  split_ifs
  

Proof state:
case pos
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulWithZero R M
s : Set α
r : α → R
f : α → M
a : α
h✝ : a ∈ s
⊢ r a • f a = r a • f a
case neg
α : Type u_1
R : Type u_2
k : Type u_3
S : Type u_4
M : Type u_5
M₂ : Type u_6
M₃ : Type u_7
ι : Type u_8
inst✝² : Zero R
inst✝¹ : Zero M
inst✝ : SMulWithZero R M
s : Set α
r : α → R
f : α → M
a : α
h✝ : a ∉ s
⊢ 0 = 0 • f a

Next tactic:
exacts [rfl, (zero_smul _ (f a)).symm]
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
⊢ IsLimit d

Next tactic:
let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
⊢ IsLimit d

Next tactic:
let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
⊢ IsLimit d

Next tactic:
let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
⊢ IsLimit d

Next tactic:
let f : d ⟶ d' := hd'.liftConeMorphism d
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
        let f : d ⟶ d' := hd'.liftConeMorphism d
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
f : d ⟶ d' := IsLimit.liftConeMorphism hd' d
⊢ IsLimit d

Next tactic:
have : (Cones.functoriality K F).map f = i.inv :=
          (hd.ofIsoLimit i.symm).uniq_cone_morphism
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
        let f : d ⟶ d' := hd'.liftConeMorphism d
        have : (Cones.functoriality K F).map f = i.inv :=
          (hd.ofIsoLimit i.symm).uniq_cone_morphism
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
f : d ⟶ d' := IsLimit.liftConeMorphism hd' d
this : (Cones.functoriality K F).map f = i.inv
⊢ IsLimit d

Next tactic:
haveI : IsIso ((Cones.functoriality K F).map f) := by
          rw [this]
          infer_instance
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
        let f : d ⟶ d' := hd'.liftConeMorphism d
        have : (Cones.functoriality K F).map f = i.inv :=
          (hd.ofIsoLimit i.symm).uniq_cone_morphism
        haveI : IsIso ((Cones.functoriality K F).map f) := by
          

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
f : d ⟶ d' := IsLimit.liftConeMorphism hd' d
this : (Cones.functoriality K F).map f = i.inv
⊢ IsIso ((Cones.functoriality K F).map f)

Next tactic:
rw [this]
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
        let f : d ⟶ d' := hd'.liftConeMorphism d
        have : (Cones.functoriality K F).map f = i.inv :=
          (hd.ofIsoLimit i.symm).uniq_cone_morphism
        haveI : IsIso ((Cones.functoriality K F).map f) := by
          rw [this]
          

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
f : d ⟶ d' := IsLimit.liftConeMorphism hd' d
this : (Cones.functoriality K F).map f = i.inv
⊢ IsIso i.inv

Next tactic:
infer_instance
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
        let f : d ⟶ d' := hd'.liftConeMorphism d
        have : (Cones.functoriality K F).map f = i.inv :=
          (hd.ofIsoLimit i.symm).uniq_cone_morphism
        haveI : IsIso ((Cones.functoriality K F).map f) := by
          rw [this]
          infer_instance
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
f : d ⟶ d' := IsLimit.liftConeMorphism hd' d
this✝ : (Cones.functoriality K F).map f = i.inv
this : IsIso ((Cones.functoriality K F).map f)
⊢ IsLimit d

Next tactic:
haveI : IsIso f := isIso_of_reflects_iso f (Cones.functoriality K F)
/-- If `F` reflects isomorphisms and we can lift any limit cone to a limit cone,
then `F` creates limits.
In particular here we don't need to assume that F reflects limits.
-/
def createsLimitOfReflectsIso {K : J ⥤ C} {F : C ⥤ D} [ReflectsIsomorphisms F]
    (h : ∀ c t, LiftsToLimit K F c t) : CreatesLimit K F
    where
  lifts c t := (h c t).toLiftableCone
  toReflectsLimit :=
    { reflects := fun {d} hd => by
        let d' : Cone K := (h (F.mapCone d) hd).toLiftableCone.liftedCone
        let i : F.mapCone d' ≅ F.mapCone d :=
          (h (F.mapCone d) hd).toLiftableCone.validLift
        let hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
        let f : d ⟶ d' := hd'.liftConeMorphism d
        have : (Cones.functoriality K F).map f = i.inv :=
          (hd.ofIsoLimit i.symm).uniq_cone_morphism
        haveI : IsIso ((Cones.functoriality K F).map f) := by
          rw [this]
          infer_instance
        haveI : IsIso f := isIso_of_reflects_iso f (Cones.functoriality K F)
        

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
J : Type w
inst✝¹ : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝ : ReflectsIsomorphisms F
h : (c : Cone (K ⋙ F)) → (t : IsLimit c) → LiftsToLimit K F c t
d : Cone K
hd : IsLimit (F.mapCone d)
d' : Cone K := (h (F.mapCone d) hd).liftedCone
i : F.mapCone d' ≅ F.mapCone d := (h (F.mapCone d) hd).validLift
hd' : IsLimit d' := (h (F.mapCone d) hd).makesLimit
f : d ⟶ d' := IsLimit.liftConeMorphism hd' d
this✝¹ : (Cones.functoriality K F).map f = i.inv
this✝ : IsIso ((Cones.functoriality K F).map f)
this : IsIso f
⊢ IsLimit d

Next tactic:
exact IsLimit.ofIsoLimit hd' (asIso f).symm
/--
When `F` is fully faithful, to show that `F` creates the limit for `K` it suffices to show that a
limit point is in the essential image of `F`.
-/
def createsLimitOfFullyFaithfulOfIso' {K : J ⥤ C} {F : C ⥤ D} [Full F] [Faithful F]
    {l : Cone (K ⋙ F)} (hl : IsLimit l) (X : C) (i : F.obj X ≅ l.pt) : CreatesLimit K F :=
  createsLimitOfFullyFaithfulOfLift' hl
    { pt := X
      π :=
        { app := fun j => F.preimage (i.hom ≫ l.π.app j)
          naturality := fun Y Z f =>
            F.map_injective <| by
              

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
J : Type w
inst✝² : Category.{w', w} J
K✝ K : J ⥤ C
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
l : Cone (K ⋙ F)
hl : IsLimit l
X : C
i : F.obj X ≅ l.pt
Y Z : J
f : Y ⟶ Z
⊢ F.map (((Functor.const J).obj X).map f ≫ (fun j => F.preimage (i.hom ≫ l.π.app j)) Z) =
    F.map ((fun j => F.preimage (i.hom ≫ l.π.app j)) Y ≫ K.map f)

Next tactic:
dsimp