l3lab/ntp-mathlib huggingface dataset:
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · 

Proof state:
case refine'_3
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
⊢ ∀ (a b : A),
    { toAddHom := src✝.toAddHom,
          map_smul' :=
            (_ :
              ∀ (r : R) (x : A), AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
        (a * b) =
      a •
          { toAddHom := src✝.toAddHom,
              map_smul' :=
                (_ :
                  ∀ (r : R) (x : A),
                    AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
            b +
        b •
          { toAddHom := src✝.toAddHom,
              map_smul' :=
                (_ :
                  ∀ (r : R) (x : A),
                    AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
            a

Next tactic:
intro x y
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    

Proof state:
case refine'_3
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
⊢ { toAddHom := src✝.toAddHom,
        map_smul' :=
          (_ :
            ∀ (r : R) (x : A), AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
      (x * y) =
    x •
        { toAddHom := src✝.toAddHom,
            map_smul' :=
              (_ :
                ∀ (r : R) (x : A),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
          y +
      y •
        { toAddHom := src✝.toAddHom,
            map_smul' :=
              (_ :
                ∀ (r : R) (x : A),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
          x

Next tactic:
let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by 

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
⊢ AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B)

Next tactic:
rw [e]
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; 

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
⊢ IsScalarTower.toAlgHom R A (B ⧸ I) = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B)

Next tactic:
ext
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; 

Proof state:
case H
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y x✝ : A
⊢ (IsScalarTower.toAlgHom R A (B ⧸ I)) x✝ = (AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B)) x✝

Next tactic:
rfl
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
    

Proof state:
case refine'_3
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
F : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
⊢ { toAddHom := src✝.toAddHom,
        map_smul' :=
          (_ :
            ∀ (r : R) (x : A), AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
      (x * y) =
    x •
        { toAddHom := src✝.toAddHom,
            map_smul' :=
              (_ :
                ∀ (r : R) (x : A),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
          y +
      y •
        { toAddHom := src✝.toAddHom,
            map_smul' :=
              (_ :
                ∀ (r : R) (x : A),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
          x

Next tactic:
have : (f x - algebraMap A B x) * (f y - algebraMap A B y) = 0 := by
      rw [← Ideal.mem_bot, ← hI, pow_two]
      convert Ideal.mul_mem_mul (F x).2 (F y).2 using 1
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
    have : (f x - algebraMap A B x) * (f y - algebraMap A B y) = 0 := by
      

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
F : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
⊢ (f x - (algebraMap A B) x) * (f y - (algebraMap A B) y) = 0

Next tactic:
rw [← Ideal.mem_bot, ← hI, pow_two]
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
    have : (f x - algebraMap A B x) * (f y - algebraMap A B y) = 0 := by
      rw [← Ideal.mem_bot, ← hI, pow_two]
      

Proof state:
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
F : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
⊢ (f x - (algebraMap A B) x) * (f y - (algebraMap A B) y) ∈ I * I

Next tactic:
convert Ideal.mul_mem_mul (F x).2 (F y).2 using 1
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
    have : (f x - algebraMap A B x) * (f y - algebraMap A B y) = 0 := by
      rw [← Ideal.mem_bot, ← hI, pow_two]
      convert Ideal.mul_mem_mul (F x).2 (F y).2 using 1
    

Proof state:
case refine'_3
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
F : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
this : (f x - (algebraMap A B) x) * (f y - (algebraMap A B) y) = 0
⊢ { toAddHom := src✝.toAddHom,
        map_smul' :=
          (_ :
            ∀ (r : R) (x : A), AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
      (x * y) =
    x •
        { toAddHom := src✝.toAddHom,
            map_smul' :=
              (_ :
                ∀ (r : R) (x : A),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
          y +
      y •
        { toAddHom := src✝.toAddHom,
            map_smul' :=
              (_ :
                ∀ (r : R) (x : A),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
          x

Next tactic:
ext
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
    have : (f x - algebraMap A B x) * (f y - algebraMap A B y) = 0 := by
      rw [← Ideal.mem_bot, ← hI, pow_two]
      convert Ideal.mul_mem_mul (F x).2 (F y).2 using 1
    ext
    

Proof state:
case refine'_3.a
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
F : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
this : (f x - (algebraMap A B) x) * (f y - (algebraMap A B) y) = 0
⊢ ↑({ toAddHom := src✝.toAddHom,
          map_smul' :=
            (_ :
              ∀ (r : R) (x : A), AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
        (x * y)) =
    ↑(x •
          { toAddHom := src✝.toAddHom,
              map_smul' :=
                (_ :
                  ∀ (r : R) (x : A),
                    AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
            y +
        y •
          { toAddHom := src✝.toAddHom,
              map_smul' :=
                (_ :
                  ∀ (r : R) (x : A),
                    AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }
            x)

Next tactic:
dsimp only [Submodule.coe_add, Submodule.coe_mk, LinearMap.coe_mk,
      diffToIdealOfQuotientCompEq_apply, Submodule.coe_smul_of_tower, IsScalarTower.coe_toAlgHom',
      LinearMap.toFun_eq_coe]
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
    have : (f x - algebraMap A B x) * (f y - algebraMap A B y) = 0 := by
      rw [← Ideal.mem_bot, ← hI, pow_two]
      convert Ideal.mul_mem_mul (F x).2 (F y).2 using 1
    ext
    dsimp only [Submodule.coe_add, Submodule.coe_mk, LinearMap.coe_mk,
      diffToIdealOfQuotientCompEq_apply, Submodule.coe_smul_of_tower, IsScalarTower.coe_toAlgHom',
      LinearMap.toFun_eq_coe]
    

Proof state:
case refine'_3.a
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
F : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
this : (f x - (algebraMap A B) x) * (f y - (algebraMap A B) y) = 0
⊢ ↑((diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
            (_ :
              AlgHom.comp (Ideal.Quotient.mkₐ R I) f =
                AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))).toAddHom
        (x * y)) =
    x •
        ↑((diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
                (_ :
                  AlgHom.comp (Ideal.Quotient.mkₐ R I) f =
                    AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))).toAddHom
            y) +
      y •
        ↑((diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
                (_ :
                  AlgHom.comp (Ideal.Quotient.mkₐ R I) f =
                    AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))).toAddHom
            x)

Next tactic:
simp only [map_mul, sub_mul, mul_sub, Algebra.smul_def] at this ⊢
/-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B`
of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/
def derivationToSquareZeroOfLift (f : A →ₐ[R] B)
    (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) :
    Derivation R A I := by
  refine'
    { diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) _ with
      map_one_eq_zero' := _
      leibniz' := _ }
  · rw [e]; ext; rfl
  · ext; change f 1 - algebraMap A B 1 = 0; rw [map_one, map_one, sub_self]
  · intro x y
    let F := diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B) (by rw [e]; ext; rfl)
    have : (f x - algebraMap A B x) * (f y - algebraMap A B y) = 0 := by
      rw [← Ideal.mem_bot, ← hI, pow_two]
      convert Ideal.mul_mem_mul (F x).2 (F y).2 using 1
    ext
    dsimp only [Submodule.coe_add, Submodule.coe_mk, LinearMap.coe_mk,
      diffToIdealOfQuotientCompEq_apply, Submodule.coe_smul_of_tower, IsScalarTower.coe_toAlgHom',
      LinearMap.toFun_eq_coe]
    simp only [map_mul, sub_mul, mul_sub, Algebra.smul_def] at this ⊢
    

Proof state:
case refine'_3.a
R : Type u
A : Type v
B : Type w
inst✝⁶ : CommSemiring R
inst✝⁵ : CommSemiring A
inst✝⁴ : CommRing B
inst✝³ : Algebra R A
inst✝² : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
inst✝¹ : Algebra A B
inst✝ : IsScalarTower R A B
f : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R A (B ⧸ I)
src✝ : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
x y : A
F : A →ₗ[R] ↥I :=
  diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
    (_ : AlgHom.comp (Ideal.Quotient.mkₐ R I) f = AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))
this : f x * f y - (algebraMap A B) x * f y - (f x * (algebraMap A B) y - (algebraMap A B) x * (algebraMap A B) y) = 0
⊢ ↑((diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
            (_ :
              AlgHom.comp (Ideal.Quotient.mkₐ R I) f =
                AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))).toAddHom
        (x * y)) =
    (algebraMap A B) x *
        ↑((diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
                (_ :
                  AlgHom.comp (Ideal.Quotient.mkₐ R I) f =
                    AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))).toAddHom
            y) +
      (algebraMap A B) y *
        ↑((diffToIdealOfQuotientCompEq I f (IsScalarTower.toAlgHom R A B)
                (_ :
                  AlgHom.comp (Ideal.Quotient.mkₐ R I) f =
                    AlgHom.comp (Ideal.Quotient.mkₐ R I) (IsScalarTower.toAlgHom R A B))).toAddHom
            x)

Next tactic:
rw [sub_eq_iff_eq_add, sub_eq_iff_eq_add] at this