l3lab/ntp-mathlib huggingface dataset:
/-- Given a function `f : X → A` where `A` is an `R`-algebra, `lift R f` is the unique lift
of `f` to a morphism of `R`-algebras `FreeAlgebra R X → A`.
-/
@[irreducible]
def lift : (X → A) ≃ (FreeAlgebra R X →ₐ[R] A) :=
  { toFun := liftAux R
    invFun := fun F ↦ F ∘ ι R
    left_inv := fun f ↦ by
      ext
      simp only [Function.comp_apply, ι_def]
      rfl
    right_inv := fun F ↦ by
      ext t
      rcases t with ⟨x⟩
      induction x
      case of =>
        change ((F : FreeAlgebra R X → A) ∘ ι R) _ = _
        simp only [Function.comp_apply, ι_def]
      case ofScalar x =>
        change algebraMap _ _ x = F (algebraMap _ _ x)
        rw [AlgHom.commutes F _]
      case add a b ha hb =>
        -- Porting note: it is necessary to declare fa and fb explicitly otherwise Lean refuses
        -- to consider `Quot.mk (Rel R X) ·` as element of FreeAlgebra R X
        let fa : FreeAlgebra R X := Quot.mk (Rel R X) a
        let fb : FreeAlgebra R X := Quot.mk (Rel R X) b
        change liftAux R (F ∘ ι R) (fa + fb) = F (fa + fb)
        rw [AlgHom.map_add, AlgHom.map_add, ha, hb]
      case mul a b ha hb =>
        let fa : FreeAlgebra R X := Quot.mk (Rel R X) a
        let fb : FreeAlgebra R X := Quot.mk (Rel R X) b
        change liftAux R (F ∘ ι R) (fa * fb) = F (fa * fb)
        

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
F : FreeAlgebra R X →ₐ[R] A
t : FreeAlgebra R X
a b : Pre R X
ha : (FreeAlgebra.liftAux R ((fun F => ⇑F ∘ ι R) F)) (Quot.mk (Rel R X) a) = F (Quot.mk (Rel R X) a)
hb : (FreeAlgebra.liftAux R ((fun F => ⇑F ∘ ι R) F)) (Quot.mk (Rel R X) b) = F (Quot.mk (Rel R X) b)
fa : FreeAlgebra R X := Quot.mk (Rel R X) a
fb : FreeAlgebra R X := Quot.mk (Rel R X) b
⊢ (FreeAlgebra.liftAux R (⇑F ∘ ι R)) (fa * fb) = F (fa * fb)

Next tactic:
rw [AlgHom.map_mul, AlgHom.map_mul, ha, hb]
@[simp]
theorem liftAux_eq (f : X → A) : liftAux R f = lift R f := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
⊢ FreeAlgebra.liftAux R f = (lift R) f

Next tactic:
rw [lift]
@[simp]
theorem liftAux_eq (f : X → A) : liftAux R f = lift R f := by
  rw [lift]
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
⊢ FreeAlgebra.liftAux R f =
    { toFun := FreeAlgebra.liftAux R, invFun := fun F => ⇑F ∘ ι R,
        left_inv := (_ : ∀ (f : X → A), (fun F => ⇑F ∘ ι R) (FreeAlgebra.liftAux R f) = f),
        right_inv := (_ : ∀ (F : FreeAlgebra R X →ₐ[R] A), FreeAlgebra.liftAux R ((fun F => ⇑F ∘ ι R) F) = F) }
      f

Next tactic:
rfl
@[simp]
theorem lift_symm_apply (F : FreeAlgebra R X →ₐ[R] A) : (lift R).symm F = F ∘ ι R := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
F : FreeAlgebra R X →ₐ[R] A
⊢ (lift R).symm F = ⇑F ∘ ι R

Next tactic:
rw [lift]
@[simp]
theorem lift_symm_apply (F : FreeAlgebra R X →ₐ[R] A) : (lift R).symm F = F ∘ ι R := by
  rw [lift]
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
F : FreeAlgebra R X →ₐ[R] A
⊢ { toFun := FreeAlgebra.liftAux R, invFun := fun F => ⇑F ∘ ι R,
          left_inv := (_ : ∀ (f : X → A), (fun F => ⇑F ∘ ι R) (FreeAlgebra.liftAux R f) = f),
          right_inv := (_ : ∀ (F : FreeAlgebra R X →ₐ[R] A), FreeAlgebra.liftAux R ((fun F => ⇑F ∘ ι R) F) = F) }.symm
      F =
    ⇑F ∘ ι R

Next tactic:
rfl
@[simp]
theorem ι_comp_lift (f : X → A) : (lift R f : FreeAlgebra R X → A) ∘ ι R = f := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
⊢ ⇑((lift R) f) ∘ ι R = f

Next tactic:
ext
@[simp]
theorem ι_comp_lift (f : X → A) : (lift R f : FreeAlgebra R X → A) ∘ ι R = f := by
  ext
  

Proof state:
case h
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
x✝ : X
⊢ (⇑((lift R) f) ∘ ι R) x✝ = f x✝

Next tactic:
rw [Function.comp_apply, ι_def, lift]
@[simp]
theorem ι_comp_lift (f : X → A) : (lift R f : FreeAlgebra R X → A) ∘ ι R = f := by
  ext
  rw [Function.comp_apply, ι_def, lift]
  

Proof state:
case h
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
x✝ : X
⊢ ({ toFun := FreeAlgebra.liftAux R, invFun := fun F => ⇑F ∘ ι R,
          left_inv := (_ : ∀ (f : X → A), (fun F => ⇑F ∘ ι R) (FreeAlgebra.liftAux R f) = f),
          right_inv := (_ : ∀ (F : FreeAlgebra R X →ₐ[R] A), FreeAlgebra.liftAux R ((fun F => ⇑F ∘ ι R) F) = F) }
        f)
      (Quot.mk (Rel R X) (Pre.of x✝)) =
    f x✝

Next tactic:
rfl
@[simp]
theorem lift_ι_apply (f : X → A) (x) : lift R f (ι R x) = f x := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
x : X
⊢ ((lift R) f) (ι R x) = f x

Next tactic:
rw [ι_def, lift]
@[simp]
theorem lift_ι_apply (f : X → A) (x) : lift R f (ι R x) = f x := by
  rw [ι_def, lift]
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
x : X
⊢ ({ toFun := FreeAlgebra.liftAux R, invFun := fun F => ⇑F ∘ ι R,
          left_inv := (_ : ∀ (f : X → A), (fun F => ⇑F ∘ ι R) (FreeAlgebra.liftAux R f) = f),
          right_inv := (_ : ∀ (F : FreeAlgebra R X →ₐ[R] A), FreeAlgebra.liftAux R ((fun F => ⇑F ∘ ι R) F) = F) }
        f)
      (Quot.mk (Rel R X) (Pre.of x)) =
    f x

Next tactic:
rfl
@[simp]
theorem lift_unique (f : X → A) (g : FreeAlgebra R X →ₐ[R] A) :
    (g : FreeAlgebra R X → A) ∘ ι R = f ↔ g = lift R f := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
g : FreeAlgebra R X →ₐ[R] A
⊢ ⇑g ∘ ι R = f ↔ g = (lift R) f

Next tactic:
rw [← (lift R).symm_apply_eq, lift]
@[simp]
theorem lift_unique (f : X → A) (g : FreeAlgebra R X →ₐ[R] A) :
    (g : FreeAlgebra R X → A) ∘ ι R = f ↔ g = lift R f := by
  rw [← (lift R).symm_apply_eq, lift]
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f : X → A
g : FreeAlgebra R X →ₐ[R] A
⊢ ⇑g ∘ ι R = f ↔
    { toFun := FreeAlgebra.liftAux R, invFun := fun F => ⇑F ∘ ι R,
            left_inv := (_ : ∀ (f : X → A), (fun F => ⇑F ∘ ι R) (FreeAlgebra.liftAux R f) = f),
            right_inv := (_ : ∀ (F : FreeAlgebra R X →ₐ[R] A), FreeAlgebra.liftAux R ((fun F => ⇑F ∘ ι R) F) = F) }.symm
        g =
      f

Next tactic:
rfl
@[simp]
theorem lift_comp_ι (g : FreeAlgebra R X →ₐ[R] A) :
    lift R ((g : FreeAlgebra R X → A) ∘ ι R) = g := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
g : FreeAlgebra R X →ₐ[R] A
⊢ (lift R) (⇑g ∘ ι R) = g

Next tactic:
rw [← lift_symm_apply]
@[simp]
theorem lift_comp_ι (g : FreeAlgebra R X →ₐ[R] A) :
    lift R ((g : FreeAlgebra R X → A) ∘ ι R) = g := by
  rw [← lift_symm_apply]
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
g : FreeAlgebra R X →ₐ[R] A
⊢ (lift R) ((lift R).symm g) = g

Next tactic:
exact (lift R).apply_symm_apply g
/-- See note [partially-applied ext lemmas]. -/
@[ext high]
theorem hom_ext {f g : FreeAlgebra R X →ₐ[R] A}
    (w : (f : FreeAlgebra R X → A) ∘ ι R = (g : FreeAlgebra R X → A) ∘ ι R) : f = g := by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f g : FreeAlgebra R X →ₐ[R] A
w : ⇑f ∘ ι R = ⇑g ∘ ι R
⊢ f = g

Next tactic:
rw [← lift_symm_apply, ← lift_symm_apply] at w
/-- See note [partially-applied ext lemmas]. -/
@[ext high]
theorem hom_ext {f g : FreeAlgebra R X →ₐ[R] A}
    (w : (f : FreeAlgebra R X → A) ∘ ι R = (g : FreeAlgebra R X → A) ∘ ι R) : f = g := by
  rw [← lift_symm_apply, ← lift_symm_apply] at w
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
f g : FreeAlgebra R X →ₐ[R] A
w : (lift R).symm f = (lift R).symm g
⊢ f = g

Next tactic:
exact (lift R).symm.injective w
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
⊢ AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
      ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))) =
    AlgHom.id R (MonoidAlgebra R (FreeMonoid X))

Next tactic:
apply MonoidAlgebra.algHom_ext
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; 

Proof state:
case h
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
⊢ ∀ (x : FreeMonoid X),
    (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
          ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
        (MonoidAlgebra.single x 1) =
      (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single x 1)

Next tactic:
intro x
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      

Proof state:
case h
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x : FreeMonoid X
⊢ (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
        ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
      (MonoidAlgebra.single x 1) =
    (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single x 1)

Next tactic:
refine FreeMonoid.recOn x ?_ ?_
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      refine FreeMonoid.recOn x ?_ ?_
      · 

Proof state:
case h.refine_1
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x : FreeMonoid X
⊢ (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
        ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
      (MonoidAlgebra.single 1 1) =
    (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single 1 1)

Next tactic:
simp
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      refine FreeMonoid.recOn x ?_ ?_
      · simp
        

Proof state:
case h.refine_1
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x : FreeMonoid X
⊢ 1 = MonoidAlgebra.single 1 1

Next tactic:
rfl
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      refine FreeMonoid.recOn x ?_ ?_
      · simp
        rfl
      · 

Proof state:
case h.refine_2
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x : FreeMonoid X
⊢ ∀ (x : X) (xs : FreeMonoid X),
    (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
            ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
          (MonoidAlgebra.single xs 1) =
        (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single xs 1) →
      (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
            ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
          (MonoidAlgebra.single (FreeMonoid.of x * xs) 1) =
        (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single (FreeMonoid.of x * xs) 1)

Next tactic:
intro x y ih
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      refine FreeMonoid.recOn x ?_ ?_
      · simp
        rfl
      · intro x y ih
        

Proof state:
case h.refine_2
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x✝ : FreeMonoid X
x : X
y : FreeMonoid X
ih :
  (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
        ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
      (MonoidAlgebra.single y 1) =
    (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single y 1)
⊢ (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
        ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
      (MonoidAlgebra.single (FreeMonoid.of x * y) 1) =
    (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single (FreeMonoid.of x * y) 1)

Next tactic:
simp at ih
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      refine FreeMonoid.recOn x ?_ ?_
      · simp
        rfl
      · intro x y ih
        simp at ih
        

Proof state:
case h.refine_2
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x✝ : FreeMonoid X
x : X
y : FreeMonoid X
ih : ((lift R) fun x => MonoidAlgebra.single (FreeMonoid.of x) 1) ((FreeMonoid.lift (ι R)) y) = MonoidAlgebra.single y 1
⊢ (AlgHom.comp ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
        ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R))))
      (MonoidAlgebra.single (FreeMonoid.of x * y) 1) =
    (AlgHom.id R (MonoidAlgebra R (FreeMonoid X))) (MonoidAlgebra.single (FreeMonoid.of x * y) 1)

Next tactic:
simp [ih]
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      refine FreeMonoid.recOn x ?_ ?_
      · simp
        rfl
      · intro x y ih
        simp at ih
        simp [ih])
    (by
      

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
⊢ AlgHom.comp ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
      ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x)) =
    AlgHom.id R (FreeAlgebra R X)

Next tactic:
ext
/-- The free algebra on `X` is "just" the monoid algebra on the free monoid on `X`.

This would be useful when constructing linear maps out of a free algebra,
for example.
-/
noncomputable def equivMonoidAlgebraFreeMonoid :
    FreeAlgebra R X ≃ₐ[R] MonoidAlgebra R (FreeMonoid X) :=
  AlgEquiv.ofAlgHom (lift R fun x ↦ (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))
    ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
    (by
      apply MonoidAlgebra.algHom_ext; intro x
      refine FreeMonoid.recOn x ?_ ?_
      · simp
        rfl
      · intro x y ih
        simp at ih
        simp [ih])
    (by
      ext
      

Proof state:
case w.h
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x✝ : X
⊢ (⇑(AlgHom.comp ((MonoidAlgebra.lift R (FreeMonoid X) (FreeAlgebra R X)) (FreeMonoid.lift (ι R)))
            ((lift R) fun x => (MonoidAlgebra.of R (FreeMonoid X)) (FreeMonoid.of x))) ∘
        ι R)
      x✝ =
    (⇑(AlgHom.id R (FreeAlgebra R X)) ∘ ι R) x✝

Next tactic:
simp
theorem algebraMap_leftInverse :
    Function.LeftInverse algebraMapInv (algebraMap R <| FreeAlgebra R X) := fun x ↦ by
  

Proof state:
R : Type u_1
inst✝² : CommSemiring R
X : Type u_2
A : Type u_3
inst✝¹ : Semiring A
inst✝ : Algebra R A
x : R
⊢ algebraMapInv ((algebraMap R (FreeAlgebra R X)) x) = x

Next tactic:
simp [algebraMapInv]
theorem ι_injective [Nontrivial R] : Function.Injective (ι R : X → FreeAlgebra R X) :=
  fun x y hoxy ↦
  by_contradiction <| by
    

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x y : X
hoxy : ι R x = ι R y
⊢ ¬x = y → False

Next tactic:
classical exact fun hxy : x ≠ y ↦
        let f : FreeAlgebra R X →ₐ[R] R := lift R fun z ↦ if x = z then (1 : R) else 0
        have hfx1 : f (ι R x) = 1 := (lift_ι_apply _ _).trans <| if_pos rfl
        have hfy1 : f (ι R y) = 1 := hoxy ▸ hfx1
        have hfy0 : f (ι R y) = 0 := (lift_ι_apply _ _).trans <| if_neg hxy
        one_ne_zero <| hfy1.symm.trans hfy0
theorem ι_injective [Nontrivial R] : Function.Injective (ι R : X → FreeAlgebra R X) :=
  fun x y hoxy ↦
  by_contradiction <| by
    classical 

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x y : X
hoxy : ι R x = ι R y
⊢ ¬x = y → False

Next tactic:
exact fun hxy : x ≠ y ↦
        let f : FreeAlgebra R X →ₐ[R] R := lift R fun z ↦ if x = z then (1 : R) else 0
        have hfx1 : f (ι R x) = 1 := (lift_ι_apply _ _).trans <| if_pos rfl
        have hfy1 : f (ι R y) = 1 := hoxy ▸ hfx1
        have hfy0 : f (ι R y) = 0 := (lift_ι_apply _ _).trans <| if_neg hxy
        one_ne_zero <| hfy1.symm.trans hfy0
@[simp]
theorem ι_ne_algebraMap [Nontrivial R] (x : X) (r : R) : ι R x ≠ algebraMap R _ r := fun h ↦ by
  

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x : X
r : R
h : ι R x = (algebraMap R (FreeAlgebra R X)) r
⊢ False

Next tactic:
let f0 : FreeAlgebra R X →ₐ[R] R := lift R 0
@[simp]
theorem ι_ne_algebraMap [Nontrivial R] (x : X) (r : R) : ι R x ≠ algebraMap R _ r := fun h ↦ by
  let f0 : FreeAlgebra R X →ₐ[R] R := lift R 0
  

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x : X
r : R
h : ι R x = (algebraMap R (FreeAlgebra R X)) r
f0 : FreeAlgebra R X →ₐ[R] R := (lift R) 0
⊢ False

Next tactic:
let f1 : FreeAlgebra R X →ₐ[R] R := lift R 1
@[simp]
theorem ι_ne_algebraMap [Nontrivial R] (x : X) (r : R) : ι R x ≠ algebraMap R _ r := fun h ↦ by
  let f0 : FreeAlgebra R X →ₐ[R] R := lift R 0
  let f1 : FreeAlgebra R X →ₐ[R] R := lift R 1
  

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x : X
r : R
h : ι R x = (algebraMap R (FreeAlgebra R X)) r
f0 : FreeAlgebra R X →ₐ[R] R := (lift R) 0
f1 : FreeAlgebra R X →ₐ[R] R := (lift R) 1
⊢ False

Next tactic:
have hf0 : f0 (ι R x) = 0 := lift_ι_apply _ _
@[simp]
theorem ι_ne_algebraMap [Nontrivial R] (x : X) (r : R) : ι R x ≠ algebraMap R _ r := fun h ↦ by
  let f0 : FreeAlgebra R X →ₐ[R] R := lift R 0
  let f1 : FreeAlgebra R X →ₐ[R] R := lift R 1
  have hf0 : f0 (ι R x) = 0 := lift_ι_apply _ _
  

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x : X
r : R
h : ι R x = (algebraMap R (FreeAlgebra R X)) r
f0 : FreeAlgebra R X →ₐ[R] R := (lift R) 0
f1 : FreeAlgebra R X →ₐ[R] R := (lift R) 1
hf0 : f0 (ι R x) = 0
⊢ False

Next tactic:
have hf1 : f1 (ι R x) = 1 := lift_ι_apply _ _
@[simp]
theorem ι_ne_algebraMap [Nontrivial R] (x : X) (r : R) : ι R x ≠ algebraMap R _ r := fun h ↦ by
  let f0 : FreeAlgebra R X →ₐ[R] R := lift R 0
  let f1 : FreeAlgebra R X →ₐ[R] R := lift R 1
  have hf0 : f0 (ι R x) = 0 := lift_ι_apply _ _
  have hf1 : f1 (ι R x) = 1 := lift_ι_apply _ _
  

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x : X
r : R
h : ι R x = (algebraMap R (FreeAlgebra R X)) r
f0 : FreeAlgebra R X →ₐ[R] R := (lift R) 0
f1 : FreeAlgebra R X →ₐ[R] R := (lift R) 1
hf0 : f0 (ι R x) = 0
hf1 : f1 (ι R x) = 1
⊢ False

Next tactic:
rw [h, f0.commutes, Algebra.id.map_eq_self] at hf0
@[simp]
theorem ι_ne_algebraMap [Nontrivial R] (x : X) (r : R) : ι R x ≠ algebraMap R _ r := fun h ↦ by
  let f0 : FreeAlgebra R X →ₐ[R] R := lift R 0
  let f1 : FreeAlgebra R X →ₐ[R] R := lift R 1
  have hf0 : f0 (ι R x) = 0 := lift_ι_apply _ _
  have hf1 : f1 (ι R x) = 1 := lift_ι_apply _ _
  rw [h, f0.commutes, Algebra.id.map_eq_self] at hf0
  

Proof state:
R : Type u_1
inst✝³ : CommSemiring R
X : Type u_2
A : Type u_3
inst✝² : Semiring A
inst✝¹ : Algebra R A
inst✝ : Nontrivial R
x : X
r : R
h : ι R x = (algebraMap R (FreeAlgebra R X)) r
f0 : FreeAlgebra R X →ₐ[R] R := (lift R) 0
f1 : FreeAlgebra R X →ₐ[R] R := (lift R) 1
hf0 : r = 0
hf1 : f1 (ι R x) = 1
⊢ False

Next tactic:
rw [h, f1.commutes, Algebra.id.map_eq_self] at hf1