l3lab/ntp-mathlib huggingface dataset:
/-- Show that `toEnvelGroup.mapAux` sends equivalent expressions to equal terms.
-/
theorem well_def {R : Type*} [Rack R] {G : Type*} [Group G] (f : R →◃ Quandle.Conj G) :
    ∀ {a b : PreEnvelGroup R},
      PreEnvelGroupRel' R a b → toEnvelGroup.mapAux f a = toEnvelGroup.mapAux f b
  | a, _, PreEnvelGroupRel'.refl => rfl
  | a, b, PreEnvelGroupRel'.symm h => (well_def f h).symm
  | a, b, PreEnvelGroupRel'.trans hac hcb => Eq.trans (well_def f hac) (well_def f hcb)
  | _, _, PreEnvelGroupRel'.congr_mul ha hb => by
    simp [toEnvelGroup.mapAux, well_def f ha, well_def f hb]
  | _, _, congr_inv ha => by simp [toEnvelGroup.mapAux, well_def f ha]
  | _, _, assoc a b c => by apply mul_assoc
  | _, _, PreEnvelGroupRel'.one_mul a => by simp [toEnvelGroup.mapAux]
  | _, _, PreEnvelGroupRel'.mul_one a => by simp [toEnvelGroup.mapAux]
  | _, _, PreEnvelGroupRel'.mul_left_inv a => by 

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
a : PreEnvelGroup R
⊢ mapAux f (PreEnvelGroup.mul (PreEnvelGroup.inv a) a) = mapAux f unit

Next tactic:
simp [toEnvelGroup.mapAux]
/-- Show that `toEnvelGroup.mapAux` sends equivalent expressions to equal terms.
-/
theorem well_def {R : Type*} [Rack R] {G : Type*} [Group G] (f : R →◃ Quandle.Conj G) :
    ∀ {a b : PreEnvelGroup R},
      PreEnvelGroupRel' R a b → toEnvelGroup.mapAux f a = toEnvelGroup.mapAux f b
  | a, _, PreEnvelGroupRel'.refl => rfl
  | a, b, PreEnvelGroupRel'.symm h => (well_def f h).symm
  | a, b, PreEnvelGroupRel'.trans hac hcb => Eq.trans (well_def f hac) (well_def f hcb)
  | _, _, PreEnvelGroupRel'.congr_mul ha hb => by
    simp [toEnvelGroup.mapAux, well_def f ha, well_def f hb]
  | _, _, congr_inv ha => by simp [toEnvelGroup.mapAux, well_def f ha]
  | _, _, assoc a b c => by apply mul_assoc
  | _, _, PreEnvelGroupRel'.one_mul a => by simp [toEnvelGroup.mapAux]
  | _, _, PreEnvelGroupRel'.mul_one a => by simp [toEnvelGroup.mapAux]
  | _, _, PreEnvelGroupRel'.mul_left_inv a => by simp [toEnvelGroup.mapAux]
  | _, _, act_incl x y => by 

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
x y : R
⊢ mapAux f (PreEnvelGroup.mul (PreEnvelGroup.mul (incl x) (incl y)) (PreEnvelGroup.inv (incl x))) =
    mapAux f (incl (x ◃ y))

Next tactic:
simp [toEnvelGroup.mapAux]
/-- Given a map from a rack to a group, lift it to being a map from the enveloping group.
More precisely, the `EnvelGroup` functor is left adjoint to `Quandle.Conj`.
-/
def toEnvelGroup.map {R : Type*} [Rack R] {G : Type*} [Group G] :
    (R →◃ Quandle.Conj G) ≃ (EnvelGroup R →* G)
    where
  toFun f :=
    { toFun := fun x =>
        Quotient.liftOn x (toEnvelGroup.mapAux f) fun a b ⟨hab⟩ =>
          toEnvelGroup.mapAux.well_def f hab
      map_one' := by
        

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
⊢ (fun x => Quotient.liftOn x (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b)) 1 = 1

Next tactic:
change Quotient.liftOn ⟦Rack.PreEnvelGroup.unit⟧ (toEnvelGroup.mapAux f) _ = 1
/-- Given a map from a rack to a group, lift it to being a map from the enveloping group.
More precisely, the `EnvelGroup` functor is left adjoint to `Quandle.Conj`.
-/
def toEnvelGroup.map {R : Type*} [Rack R] {G : Type*} [Group G] :
    (R →◃ Quandle.Conj G) ≃ (EnvelGroup R →* G)
    where
  toFun f :=
    { toFun := fun x =>
        Quotient.liftOn x (toEnvelGroup.mapAux f) fun a b ⟨hab⟩ =>
          toEnvelGroup.mapAux.well_def f hab
      map_one' := by
        change Quotient.liftOn ⟦Rack.PreEnvelGroup.unit⟧ (toEnvelGroup.mapAux f) _ = 1
        

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
⊢ Quotient.liftOn ⟦unit⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) = 1

Next tactic:
simp only [Quotient.lift_mk, mapAux]
/-- Given a map from a rack to a group, lift it to being a map from the enveloping group.
More precisely, the `EnvelGroup` functor is left adjoint to `Quandle.Conj`.
-/
def toEnvelGroup.map {R : Type*} [Rack R] {G : Type*} [Group G] :
    (R →◃ Quandle.Conj G) ≃ (EnvelGroup R →* G)
    where
  toFun f :=
    { toFun := fun x =>
        Quotient.liftOn x (toEnvelGroup.mapAux f) fun a b ⟨hab⟩ =>
          toEnvelGroup.mapAux.well_def f hab
      map_one' := by
        change Quotient.liftOn ⟦Rack.PreEnvelGroup.unit⟧ (toEnvelGroup.mapAux f) _ = 1
        simp only [Quotient.lift_mk, mapAux]
      map_mul' := fun x y =>
        Quotient.inductionOn₂ x y fun x y => by
          

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
x✝ y✝ : EnvelGroup R
x y : PreEnvelGroup R
⊢ OneHom.toFun
      { toFun := fun x => Quotient.liftOn x (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b),
        map_one' :=
          (_ : Quotient.liftOn ⟦unit⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) = 1) }
      (⟦x⟧ * ⟦y⟧) =
    OneHom.toFun
        {
          toFun := fun x =>
            Quotient.liftOn x (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b),
          map_one' :=
            (_ :
              Quotient.liftOn ⟦unit⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) = 1) }
        ⟦x⟧ *
      OneHom.toFun
        {
          toFun := fun x =>
            Quotient.liftOn x (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b),
          map_one' :=
            (_ :
              Quotient.liftOn ⟦unit⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) = 1) }
        ⟦y⟧

Next tactic:
simp only [toEnvelGroup.mapAux]
/-- Given a map from a rack to a group, lift it to being a map from the enveloping group.
More precisely, the `EnvelGroup` functor is left adjoint to `Quandle.Conj`.
-/
def toEnvelGroup.map {R : Type*} [Rack R] {G : Type*} [Group G] :
    (R →◃ Quandle.Conj G) ≃ (EnvelGroup R →* G)
    where
  toFun f :=
    { toFun := fun x =>
        Quotient.liftOn x (toEnvelGroup.mapAux f) fun a b ⟨hab⟩ =>
          toEnvelGroup.mapAux.well_def f hab
      map_one' := by
        change Quotient.liftOn ⟦Rack.PreEnvelGroup.unit⟧ (toEnvelGroup.mapAux f) _ = 1
        simp only [Quotient.lift_mk, mapAux]
      map_mul' := fun x y =>
        Quotient.inductionOn₂ x y fun x y => by
          simp only [toEnvelGroup.mapAux]
          

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
x✝ y✝ : EnvelGroup R
x y : PreEnvelGroup R
⊢ Quotient.liftOn (⟦x⟧ * ⟦y⟧) (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) =
    Quotient.liftOn ⟦x⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) *
      Quotient.liftOn ⟦y⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b)

Next tactic:
change Quotient.liftOn ⟦mul x y⟧ (toEnvelGroup.mapAux f) _ = _
/-- Given a map from a rack to a group, lift it to being a map from the enveloping group.
More precisely, the `EnvelGroup` functor is left adjoint to `Quandle.Conj`.
-/
def toEnvelGroup.map {R : Type*} [Rack R] {G : Type*} [Group G] :
    (R →◃ Quandle.Conj G) ≃ (EnvelGroup R →* G)
    where
  toFun f :=
    { toFun := fun x =>
        Quotient.liftOn x (toEnvelGroup.mapAux f) fun a b ⟨hab⟩ =>
          toEnvelGroup.mapAux.well_def f hab
      map_one' := by
        change Quotient.liftOn ⟦Rack.PreEnvelGroup.unit⟧ (toEnvelGroup.mapAux f) _ = 1
        simp only [Quotient.lift_mk, mapAux]
      map_mul' := fun x y =>
        Quotient.inductionOn₂ x y fun x y => by
          simp only [toEnvelGroup.mapAux]
          change Quotient.liftOn ⟦mul x y⟧ (toEnvelGroup.mapAux f) _ = _
          

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
x✝ y✝ : EnvelGroup R
x y : PreEnvelGroup R
⊢ Quotient.liftOn ⟦PreEnvelGroup.mul x y⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) =
    Quotient.liftOn ⟦x⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b) *
      Quotient.liftOn ⟦y⟧ (mapAux f) (_ : ∀ (a b : PreEnvelGroup R), a ≈ b → mapAux f a = mapAux f b)

Next tactic:
simp [toEnvelGroup.mapAux]
/-- Given a map from a rack to a group, lift it to being a map from the enveloping group.
More precisely, the `EnvelGroup` functor is left adjoint to `Quandle.Conj`.
-/
def toEnvelGroup.map {R : Type*} [Rack R] {G : Type*} [Group G] :
    (R →◃ Quandle.Conj G) ≃ (EnvelGroup R →* G)
    where
  toFun f :=
    { toFun := fun x =>
        Quotient.liftOn x (toEnvelGroup.mapAux f) fun a b ⟨hab⟩ =>
          toEnvelGroup.mapAux.well_def f hab
      map_one' := by
        change Quotient.liftOn ⟦Rack.PreEnvelGroup.unit⟧ (toEnvelGroup.mapAux f) _ = 1
        simp only [Quotient.lift_mk, mapAux]
      map_mul' := fun x y =>
        Quotient.inductionOn₂ x y fun x y => by
          simp only [toEnvelGroup.mapAux]
          change Quotient.liftOn ⟦mul x y⟧ (toEnvelGroup.mapAux f) _ = _
          simp [toEnvelGroup.mapAux] }
  invFun F := (Quandle.Conj.map F).comp (toEnvelGroup R)
  left_inv f := by ext; rfl
  right_inv F :=
    MonoidHom.ext fun x =>
      Quotient.inductionOn x fun x => by
        induction' x with _ x y ih_x ih_y x ih_x
        · exact F.map_one.symm
        · rfl
        · have hm : ⟦x.mul y⟧ = @Mul.mul (EnvelGroup R) _ ⟦x⟧ ⟦y⟧ := rfl
          simp only [MonoidHom.coe_mk, OneHom.coe_mk, Quotient.lift_mk]
          suffices ∀ x y, F (Mul.mul x y) = F (x) * F (y) by
            simp_all only [MonoidHom.coe_mk, OneHom.coe_mk, Quotient.lift_mk, hm]
            

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
F : EnvelGroup R →* G
x✝ : EnvelGroup R
x y : PreEnvelGroup R
ih_x : mapAux (ShelfHom.comp (Quandle.Conj.map F) (toEnvelGroup R)) x = F ⟦x⟧
ih_y : mapAux (ShelfHom.comp (Quandle.Conj.map F) (toEnvelGroup R)) y = F ⟦y⟧
hm : ⟦PreEnvelGroup.mul x y⟧ = Mul.mul ⟦x⟧ ⟦y⟧
this : ∀ (x y : EnvelGroup R), F (Mul.mul x y) = F x * F y
⊢ mapAux (ShelfHom.comp (Quandle.Conj.map F) (toEnvelGroup R)) (PreEnvelGroup.mul x y) = F ⟦x⟧ * F ⟦y⟧

Next tactic:
rw [← ih_x, ← ih_y, mapAux]
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
⊢ IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x

Next tactic:
let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
⊢ IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x

Next tactic:
constructor
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · 

Proof state:
case mp
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
⊢ IsIntegrallyClosed R → ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x

Next tactic:
rintro ⟨cl⟩
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · rintro ⟨cl⟩
    

Proof state:
case mp.mk
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
cl : ∀ {x : FractionRing R}, IsIntegral R x → ∃ y, (algebraMap R (FractionRing R)) y = x
⊢ ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x

Next tactic:
refine' fun hx => _
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · rintro ⟨cl⟩
    refine' fun hx => _
    

Proof state:
case mp.mk
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
cl : ∀ {x : FractionRing R}, IsIntegral R x → ∃ y, (algebraMap R (FractionRing R)) y = x
x✝ : K
hx : IsIntegral R x✝
⊢ ∃ y, (algebraMap R K) y = x✝

Next tactic:
obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e).mpr hx)
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · rintro ⟨cl⟩
    refine' fun hx => _
    obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e).mpr hx)
    

Proof state:
case mp.mk.intro
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
cl : ∀ {x : FractionRing R}, IsIntegral R x → ∃ y, (algebraMap R (FractionRing R)) y = x
x✝ : K
hx : IsIntegral R x✝
y : R
hy : (algebraMap R (FractionRing R)) y = e x✝
⊢ ∃ y, (algebraMap R K) y = x✝

Next tactic:
exact ⟨y, e.algebraMap_eq_apply.mp hy⟩
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · rintro ⟨cl⟩
    refine' fun hx => _
    obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e).mpr hx)
    exact ⟨y, e.algebraMap_eq_apply.mp hy⟩
  · 

Proof state:
case mpr
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
⊢ (∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x) → IsIntegrallyClosed R

Next tactic:
rintro cl
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · rintro ⟨cl⟩
    refine' fun hx => _
    obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e).mpr hx)
    exact ⟨y, e.algebraMap_eq_apply.mp hy⟩
  · rintro cl
    

Proof state:
case mpr
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
cl : ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x
⊢ IsIntegrallyClosed R

Next tactic:
refine' ⟨fun hx => _⟩
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · rintro ⟨cl⟩
    refine' fun hx => _
    obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e).mpr hx)
    exact ⟨y, e.algebraMap_eq_apply.mp hy⟩
  · rintro cl
    refine' ⟨fun hx => _⟩
    

Proof state:
case mpr
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
cl : ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x
x✝ : FractionRing R
hx : IsIntegral R x✝
⊢ ∃ y, (algebraMap R (FractionRing R)) y = x✝

Next tactic:
obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e.symm).mpr hx)
/-- `R` is integrally closed iff all integral elements of its fraction field `K`
are also elements of `R`. -/
theorem isIntegrallyClosed_iff :
    IsIntegrallyClosed R ↔ ∀ {x : K}, IsIntegral R x → ∃ y, algebraMap R K y = x := by
  let e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ _ _
  constructor
  · rintro ⟨cl⟩
    refine' fun hx => _
    obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e).mpr hx)
    exact ⟨y, e.algebraMap_eq_apply.mp hy⟩
  · rintro cl
    refine' ⟨fun hx => _⟩
    obtain ⟨y, hy⟩ := cl ((isIntegral_algEquiv e.symm).mpr hx)
    

Proof state:
case mpr.intro
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
e : K ≃ₐ[R] FractionRing R := IsLocalization.algEquiv R⁰ K (FractionRing R)
cl : ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x
x✝ : FractionRing R
hx : IsIntegral R x✝
y : R
hy : (algebraMap R K) y = (AlgEquiv.symm e) x✝
⊢ ∃ y, (algebraMap R (FractionRing R)) y = x✝

Next tactic:
exact ⟨y, e.symm.algebraMap_eq_apply.mp hy⟩
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    

Proof state:
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
⊢ (∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x) ↔ IsIntegralClosure R R K

Next tactic:
constructor
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    constructor
    · 

Proof state:
case mp
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
⊢ (∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x) → IsIntegralClosure R R K

Next tactic:
intro cl
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    constructor
    · intro cl
      

Proof state:
case mp
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
cl : ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x
⊢ IsIntegralClosure R R K

Next tactic:
refine' ⟨IsFractionRing.injective R K, ⟨cl, _⟩⟩
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    constructor
    · intro cl
      refine' ⟨IsFractionRing.injective R K, ⟨cl, _⟩⟩
      

Proof state:
case mp
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
cl : ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x
x✝ : K
⊢ (∃ y, (algebraMap R K) y = x✝) → IsIntegral R x✝

Next tactic:
rintro ⟨y, y_eq⟩
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    constructor
    · intro cl
      refine' ⟨IsFractionRing.injective R K, ⟨cl, _⟩⟩
      rintro ⟨y, y_eq⟩
      

Proof state:
case mp.intro
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
cl : ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x
x✝ : K
y : R
y_eq : (algebraMap R K) y = x✝
⊢ IsIntegral R x✝

Next tactic:
rw [← y_eq]
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    constructor
    · intro cl
      refine' ⟨IsFractionRing.injective R K, ⟨cl, _⟩⟩
      rintro ⟨y, y_eq⟩
      rw [← y_eq]
      

Proof state:
case mp.intro
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
cl : ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x
x✝ : K
y : R
y_eq : (algebraMap R K) y = x✝
⊢ IsIntegral R ((algebraMap R K) y)

Next tactic:
exact isIntegral_algebraMap
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    constructor
    · intro cl
      refine' ⟨IsFractionRing.injective R K, ⟨cl, _⟩⟩
      rintro ⟨y, y_eq⟩
      rw [← y_eq]
      exact isIntegral_algebraMap
    · 

Proof state:
case mpr
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
⊢ IsIntegralClosure R R K → ∀ {x : K}, IsIntegral R x → ∃ y, (algebraMap R K) y = x

Next tactic:
rintro ⟨-, cl⟩ x hx
/-- `R` is integrally closed iff it is the integral closure of itself in its field of fractions. -/
theorem isIntegrallyClosed_iff_isIntegralClosure : IsIntegrallyClosed R ↔ IsIntegralClosure R R K :=
  (isIntegrallyClosed_iff K).trans <| by
    constructor
    · intro cl
      refine' ⟨IsFractionRing.injective R K, ⟨cl, _⟩⟩
      rintro ⟨y, y_eq⟩
      rw [← y_eq]
      exact isIntegral_algebraMap
    · rintro ⟨-, cl⟩ x hx
      

Proof state:
case mpr.mk
R : Type u_1
inst✝³ : CommRing R
K : Type u_2
inst✝² : CommRing K
inst✝¹ : Algebra R K
inst✝ : IsFractionRing R K
cl : ∀ {x : K}, IsIntegral R x ↔ ∃ y, (algebraMap R K) y = x
x : K
hx : IsIntegral R x
⊢ ∃ y, (algebraMap R K) y = x

Next tactic:
exact cl.mp hx
lemma _root_.IsIntegralClosure.of_isIntegrallyClosed
    [Algebra S R] [Algebra S K] [IsScalarTower S R K] (hRS : Algebra.IsIntegral S R) :
    IsIntegralClosure R S K := by
  

Proof state:
R : Type u_1
S : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : CommRing S
id : IsDomain R
iic : IsIntegrallyClosed R
K : Type u_3
inst✝⁴ : CommRing K
inst✝³ : Algebra R K
ifr : IsFractionRing R K
inst✝² : Algebra S R
inst✝¹ : Algebra S K
inst✝ : IsScalarTower S R K
hRS : Algebra.IsIntegral S R
⊢ IsIntegralClosure R S K

Next tactic:
refine ⟨IsLocalization.injective _ le_rfl, fun {x} ↦
    ⟨fun hx ↦ IsIntegralClosure.isIntegral_iff.mp (IsIntegral.tower_top (A := R) hx), ?_⟩⟩
lemma _root_.IsIntegralClosure.of_isIntegrallyClosed
    [Algebra S R] [Algebra S K] [IsScalarTower S R K] (hRS : Algebra.IsIntegral S R) :
    IsIntegralClosure R S K := by
  refine ⟨IsLocalization.injective _ le_rfl, fun {x} ↦
    ⟨fun hx ↦ IsIntegralClosure.isIntegral_iff.mp (IsIntegral.tower_top (A := R) hx), ?_⟩⟩
  

Proof state:
R : Type u_1
S : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : CommRing S
id : IsDomain R
iic : IsIntegrallyClosed R
K : Type u_3
inst✝⁴ : CommRing K
inst✝³ : Algebra R K
ifr : IsFractionRing R K
inst✝² : Algebra S R
inst✝¹ : Algebra S K
inst✝ : IsScalarTower S R K
hRS : Algebra.IsIntegral S R
x : K
⊢ (∃ y, (algebraMap R K) y = x) → IsIntegral S x

Next tactic:
rintro ⟨y, rfl⟩