[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.RingTheory.Coalgebra.Basic).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem rTensor_counit_comul (a : A) : counit.rTensor A (comul a) = 1 ⊗ₜ[R] a
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.coassoc_apply (L95-L98)
theorem coassoc_apply (a : A) :
    TensorProduct.assoc R A A A (comul.rTensor A (comul a)) = comul.lTensor A (comul a) :=
LinearMap.congr_fun coassoc a
```

-- snippet 2
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.coassoc_symm_apply (L100-L103)
theorem coassoc_symm_apply (a : A) :
    (TensorProduct.assoc R A A A).symm (comul.lTensor A (comul a)) = comul.rTensor A (comul a) := by
rw [(TensorProduct.assoc R A A A).symm_apply_eq, coassoc_apply a]
```

-- snippet 3
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.coassoc_symm (L105-L109)
theorem coassoc_symm :
    (TensorProduct.assoc R A A A).symm ∘ₗ comul.lTensor A ∘ₗ comul =
    comul.rTensor A ∘ₗ (comul (R := R)) :=
LinearMap.ext coassoc_symm_apply
```

-- snippet 4
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.lTensor_counit_comul (L115-L117)
theorem lTensor_counit_comul (a : A) : counit.lTensor A (comul a) = a ⊗ₜ[R] 1 :=
LinearMap.congr_fun lTensor_counit_comp_comul a
```

-- snippet 5
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_counit_tmul_eq (L119-L122)
lemma sum_counit_tmul_eq {a : A} (repr : Coalgebra.Repr R a) :
    ∑ i ∈ repr.index, counit (R := R) (repr.left i) ⊗ₜ (repr.right i) = 1 ⊗ₜ[R] a := by
simpa [← repr.eq, map_sum] using congr($(rTensor_counit_comp_comul (R := R) (A := A)) a)
```

-- snippet 6
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_tmul_counit_eq (L124-L128)
lemma sum_tmul_counit_eq {a : A} (repr : Coalgebra.Repr R a) :
    ∑ i ∈ repr.index, (repr.left i) ⊗ₜ counit (R := R) (repr.right i) = a ⊗ₜ[R] 1 := by
simpa [← repr.eq, map_sum] using congr($(lTensor_counit_comp_comul (R := R) (A := A)) a)

-- Cannot be @[simp] because `a₂` cannot be inferred by `simp`.
```

-- snippet 7
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_tmul_tmul_eq (L129-L137)
lemma sum_tmul_tmul_eq {a : A} (repr : Repr R a)
    (a₁ : (i : repr.ι) → Repr R (repr.left i)) (a₂ : (i : repr.ι) → Repr R (repr.right i)) :
    ∑ i ∈ repr.index, ∑ j ∈ (a₁ i).index,
      (a₁ i).left j ⊗ₜ[R] ((a₁ i).right j ⊗ₜ[R] repr.right i)
      = ∑ i ∈ repr.index, ∑ j ∈ (a₂ i).index,
      repr.left i ⊗ₜ[R] ((a₂ i).left j ⊗ₜ[R] (a₂ i).right j) := by
simpa [(a₂ _).eq, ← (a₁ _).eq, ← TensorProduct.tmul_sum,
    TensorProduct.sum_tmul, ← repr.eq] using congr($(coassoc (R := R)) a)
```

-- snippet 8
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_counit_tmul_map_eq (L139-L145)
theorem sum_counit_tmul_map_eq {B : Type*} [AddCommMonoid B] [Module R B]
    {F : Type*} [FunLike F A B] [LinearMapClass F R A B] (f : F) (a : A) {repr : Repr R a} :
    ∑ i ∈ repr.index, counit (R := R) (repr.left i) ⊗ₜ f (repr.right i) = 1 ⊗ₜ[R] f a := by
have := sum_counit_tmul_eq repr
  apply_fun LinearMap.lTensor R (f : A →ₗ[R] B) at this
  simp_all only [map_sum, LinearMap.lTensor_tmul, LinearMap.coe_coe]
```

-- snippet 9
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_map_tmul_counit_eq (L147-L154)
theorem sum_map_tmul_counit_eq {B : Type*} [AddCommMonoid B] [Module R B]
    {F : Type*} [FunLike F A B] [LinearMapClass F R A B] (f : F) (a : A) {repr : Repr R a} :
    ∑ i ∈ repr.index, f (repr.left i) ⊗ₜ counit (R := R) (repr.right i) = f a ⊗ₜ[R] 1 := by
have := sum_tmul_counit_eq repr
  apply_fun LinearMap.rTensor R (f : A →ₗ[R] B) at this
  simp_all only [map_sum, LinearMap.rTensor_tmul, LinearMap.coe_coe]

-- Cannot be @[simp] because `a₁` cannot be inferred by `simp`.
```

-- snippet 10
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_map_tmul_tmul_eq (L155-L166)
theorem sum_map_tmul_tmul_eq {B : Type*} [AddCommMonoid B] [Module R B]
    {F : Type*} [FunLike F A B] [LinearMapClass F R A B] (f g h : F) (a : A) {repr : Repr R a}
    {a₁ : (i : repr.ι) → Repr R (repr.left i)} {a₂ : (i : repr.ι) → Repr R (repr.right i)} :
    ∑ i ∈ repr.index, ∑ j ∈ (a₂ i).index,
      f (repr.left i) ⊗ₜ (g ((a₂ i).left j) ⊗ₜ h ((a₂ i).right j)) =
    ∑ i ∈ repr.index, ∑ j ∈ (a₁ i).index,
      f ((a₁ i).left j) ⊗ₜ[R] (g ((a₁ i).right j) ⊗ₜ[R] h (repr.right i)) := by
have := sum_tmul_tmul_eq repr a₁ a₂
  apply_fun TensorProduct.map (f : A →ₗ[R] B)
    (TensorProduct.map (g : A →ₗ[R] B) (h : A →ₗ[R] B)) at this
  simp_all only [map_sum, TensorProduct.map_tmul, LinearMap.coe_coe]
```

-- snippet 11
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_counit_smul (L167-L171)
lemma sum_counit_smul (𝓡 : Repr R a) :
    ∑ x ∈ 𝓡.index, counit (R := R) (𝓡.left x) • 𝓡.right x = a := by
simpa only [map_sum, TensorProduct.lift.tmul, LinearMap.lsmul_apply, one_smul]
    using congr(TensorProduct.lift (LinearMap.lsmul R A) $(sum_counit_tmul_eq (R := R) 𝓡))
```

-- snippet 12
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.lift_lsmul_comp_counit_comp_comul (L172-L189)
lemma lift_lsmul_comp_counit_comp_comul :
    TensorProduct.lift (.lsmul R A ∘ₗ counit) ∘ₗ comul = .id := by
have := rTensor_counit_comp_comul (R := R) (A := A)
  apply_fun (TensorProduct.lift (LinearMap.lsmul R A) ∘ₗ ·) at this
  rw [LinearMap.rTensor, ← LinearMap.comp_assoc, TensorProduct.lift_comp_map, LinearMap.compl₂_id]
    at this
  ext
  simp [this]

variable (R A) in
/-- A coalgebra `A` is cocommutative if its comultiplication `δ : A → A ⊗ A` commutes with the
swapping `β : A ⊗ A ≃ A ⊗ A` of the factors in the tensor product. -/
class IsCocomm where
  protected comm_comp_comul : (TensorProduct.comm R A A).comp comul = comul

variable [IsCocomm R A]

variable (R A) in
```

-- snippet 13
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.toCoalgebra (L205-L211)
instance toCoalgebra : Coalgebra R R where
  comul := (TensorProduct.mk R R R) 1
counit := .id
  coassoc := rfl
  rTensor_counit_comp_comul := by ext; rfl
  lTensor_counit_comp_comul := by ext; rfl
```

-- snippet 14
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.comul_apply (L213-L214)
theorem comul_apply (r : R) : comul r = 1 ⊗ₜ[R] r := rfl
```

-- snippet 15
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.counit_apply (L216-L217)
theorem counit_apply (r : R) : counit r = r := rfl
```

-- snippet 16
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgEquiv (L58-L61)
def toCoalgEquiv [EquivLike F A B] [CoalgEquivClass F R A B] (f : F) : A ≃ₗc[R] B :=
{ (f : A →ₗc[R] B), (f : A ≃ₗ[R] B) with }

/-- Reinterpret an element of a type of coalgebra equivalences as a coalgebra equivalence. -/
```

-- snippet 17
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgHom_inj (L110-L112)
theorem toCoalgHom_inj {e₁ e₂ : A ≃ₗc[R] B} : (↑e₁ : A →ₗc[R] B) = e₂ ↔ e₁ = e₂ :=
toCoalgHom_injective.eq_iff
```

-- snippet 18
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convNonUnitalSemiring (L123-L144)
instance convNonUnitalSemiring : NonUnitalSemiring (WithConv (C →ₗ[R] A)) where
  mul_assoc f g h := toConv_injective.eq_iff.mpr <| calc
_ = (μ ∘ₗ rTensor _ μ) ∘ₗ (((f.ofConv ⊗ₘ g.ofConv) ⊗ₘ h.ofConv) ∘ₗ
        (TensorProduct.assoc R C C C).symm) ∘ₗ lTensor C δ ∘ₗ δ := by
      ext; simp [comp_assoc, coassoc_symm, convMul_def]
    _ = (μ ∘ₗ rTensor A μ ∘ₗ ↑(TensorProduct.assoc R A A A).symm) ∘ₗ
        (f.ofConv ⊗ₘ (g.ofConv ⊗ₘ h.ofConv)) ∘ₗ lTensor C δ ∘ₗ δ := by
      simp only [map_map_comp_assoc_symm_eq, comp_assoc]
    _ = (μ ∘ₗ .lTensor _ μ) ∘ₗ (f.ofConv ⊗ₘ (g.ofConv ⊗ₘ h.ofConv)) ∘ₗ (lTensor C δ ∘ₗ δ) := by
      congr 1
      ext
      simp [mul_assoc]
    _ = μ ∘ₗ (f.ofConv ⊗ₘ μ ∘ₗ (g.ofConv ⊗ₘ h.ofConv) ∘ₗ δ) ∘ₗ δ := by ext; simp

end NonUnitalSemiring

section NonUnitalRing
variable [NonUnitalRing A] [AddCommMonoid C] [Module R A] [SMulCommClass R A A]
  [IsScalarTower R A A] [Module R C] [Coalgebra R C]

/-- Non-unital convolution ring structure on linear maps from a coalgebra to a
non-unital algebra. -/
```

-- snippet 19
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_coe (L127-L129)
theorem coe_coe : ⇑(e : A →ₗc[R] B) = e :=
rfl
```

-- snippet 20
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_toLinearEquiv (L139-L141)
theorem coe_toLinearEquiv : ⇑(e : A ≃ₗ[R] B) = e :=
rfl
```

-- snippet 21
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul_comp_coalgHom_distrib (L115-L122)
lemma convMul_comp_coalgHom_distrib [AddCommMonoid B] [Module R B] [CoalgebraStruct R B]
    (f g : WithConv (C →ₗ[R] A)) (h : B →ₗc[R] C) :
    (f * g).ofConv.comp h.toLinearMap =
      (toConv (f.ofConv.comp h.toLinearMap) * toConv (g.ofConv.comp h.toLinearMap)).ofConv := by
simp [convMul_def, map_comp, comp_assoc]

/-- Non-unital convolution semiring structure on linear maps from a coalgebra to a
non-unital algebra. -/
```

-- snippet 22
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul_apply (L62-L64)
lemma convMul_apply (f g : WithConv (C →ₗ[R] A)) (c : C) :
    (f * g) c = mul' R A (.map f.ofConv g.ofConv (comul c)) := rfl
```

-- snippet 23
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul (L55-L57)
instance convMul : Mul (WithConv (C →ₗ[R] A)) where
  mul f g := toConv (mul' R A ∘ₗ map f.ofConv g.ofConv ∘ₗ comul)
```

-- snippet 24
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_toCoalgHom (L143-L145)
theorem coe_toCoalgHom : ⇑(e : A →ₗc[R] B) = e :=
rfl
```

-- snippet 25
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convOne (L165-L166)
instance convOne : One (WithConv (C →ₗ[R] A)) where one := toConv (Algebra.linearMap R A ∘ₗ counit)
```

-- snippet 26
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.instCoeToCoalgEquiv (L62-L71)
instance instCoeToCoalgEquiv
    [EquivLike F A B] [CoalgEquivClass F R A B] : CoeHead F (A ≃ₗc[R] B) where
  coe f := toCoalgEquiv f
end CoalgEquivClass

namespace CoalgEquiv

variable [CommSemiring R]
```

-- snippet 27
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgHom_eq_coe (L135-L137)
theorem toCoalgHom_eq_coe (f : A ≃ₗc[R] B) : f.toCoalgHom = f :=
rfl
```

-- snippet 28
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.algHom_comp_convMul_distrib (L155-L164)
lemma algHom_comp_convMul_distrib (h : A →ₐ B) (f g : WithConv (C →ₗ[R] A)) :
    h.toLinearMap.comp (f * g).ofConv =
      (toConv (h.toLinearMap.comp f.ofConv) * toConv (h.toLinearMap.comp g.ofConv)).ofConv := by
simp [convMul_def, map_comp, ← comp_assoc, AlgHom.comp_mul']

end CoalgebraStruct

variable [Coalgebra R C]

/-- Convolution unit on linear maps from a coalgebra to an algebra. -/
```

-- snippet 29
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convNonUnitalNonAssocSemiring (L71-L76)
instance convNonUnitalNonAssocSemiring : NonUnitalNonAssocSemiring (WithConv (C →ₗ[R] A)) where
  left_distrib f g h := by ext; simp [map_add_right]
right_distrib f g h := by ext; simp [map_add_left]
  zero_mul f := by ext; simp
  mul_zero f := by ext; simp
```

-- snippet 30
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toLinearEquiv_eq_coe (L131-L133)
theorem toLinearEquiv_eq_coe (f : A ≃ₗc[R] B) : f.toLinearEquiv = f :=
rfl
```

-- snippet 31
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convOne_def (L167-L168)
lemma convOne_def : (1 : WithConv (C →ₗ[R] A)) = toConv (Algebra.linearMap R A ∘ₗ counit) := rfl
```

-- snippet 32
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul_def (L58-L60)
lemma convMul_def (f g : WithConv (C →ₗ[R] A)) :
    f * g = toConv (mul' R A ∘ₗ map f.ofConv g.ofConv ∘ₗ comul) := rfl
```

-- snippet 33
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_mk (L114-L116)
theorem coe_mk {f h h₀ h₁ h₂ h₃ h₄ h₅} :
    (⟨⟨⟨⟨f, h⟩, h₀⟩, h₁, h₂⟩, h₃, h₄, h₅⟩ : A ≃ₗc[R] B) = f := rfl
```

-- snippet 34
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toEquiv_inj (L86-L88)
theorem toEquiv_inj {e₁ e₂ : A ≃ₗc[R] B} : e₁.toEquiv = e₂.toEquiv ↔ e₁ = e₂ :=
toEquiv_injective.eq_iff
```

-- snippet 35
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.nonUnitalAlgHom_comp_convMul_distrib (L108-L114)
lemma nonUnitalAlgHom_comp_convMul_distrib
    [NonUnitalNonAssocSemiring B] [Module R B] [SMulCommClass R B B] [IsScalarTower R B B]
    (h : A →ₙₐ[R] B) (f g : WithConv (C →ₗ[R] A)) :
    (h : A →ₗ[R] B).comp (f * g).ofConv =
      (toConv ((h : A →ₗ[R] B).comp f.ofConv) * toConv ((h : A →ₗ[R] B).comp g.ofConv)).ofConv := by
simp [convMul_def, map_comp, ← comp_assoc, NonUnitalAlgHom.comp_mul']
```

-- snippet 36
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convSemiring (L173-L184)
instance convSemiring : Semiring (WithConv (C →ₗ[R] A)) where
  one_mul f := by ext; simp [convOne_def, ← map_comp_rTensor]
mul_one f := by ext; simp [convOne_def, ← map_comp_lTensor]

end Semiring

section CommSemiring
variable [CommSemiring A] [AddCommMonoid C] [Algebra R A] [Module R C] [Coalgebra R C]
  [IsCocomm R C]

/-- Commutative convolution semiring structure on linear maps from a cocommutative coalgebra to an
algebra. -/
```

-- snippet 37
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convCommSemiring (L185-L193)
instance convCommSemiring : CommSemiring (WithConv (C →ₗ[R] A)) where
  mul_comm f g := by ext x; rw [convMul_apply, ← comm_comul R x, map_comm, mul'_comm, convMul_apply]
end CommSemiring

section Ring
variable [Ring A] [AddCommMonoid C] [Algebra R A] [Module R C] [Coalgebra R C]

/-- Convolution ring structure on linear maps from a coalgebra to an algebra. -/
```

-- snippet 38
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toEquiv_injective (L80-L84)
theorem toEquiv_injective : Function.Injective (toEquiv : (A ≃ₗc[R] B) → A ≃ B) :=
fun ⟨_, _, _, _⟩ ⟨_, _, _, _⟩ h =>
    (CoalgEquiv.mk.injEq _ _ _ _ _ _ _ _).mpr
      ⟨CoalgHom.ext (congr_fun (Equiv.mk.inj h).1), (Equiv.mk.inj h).2⟩
```

-- snippet 39
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toEquiv (L78-L79)
def toEquiv : (A ≃ₗc[R] B) → A ≃ B := fun f => f.toLinearEquiv.toEquiv
```

-- snippet 40
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgHom_injective (L89-L91)
theorem toCoalgHom_injective : Function.Injective (toCoalgHom : (A ≃ₗc[R] B) → A →ₗc[R] B) :=
fun _ _ H => toEquiv_injective <| Equiv.ext <| CoalgHom.congr_fun H
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.RingTheory.Coalgebra.Basic).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem rTensor_counit_comul (a : A) : counit.rTensor A (comul a) = 1 ⊗ₜ[R] a
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.coassoc_apply (L95-L98)
theorem coassoc_apply (a : A) :
    TensorProduct.assoc R A A A (comul.rTensor A (comul a)) = comul.lTensor A (comul a) :=
LinearMap.congr_fun coassoc a
```

-- snippet 2
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.coassoc_symm_apply (L100-L103)
theorem coassoc_symm_apply (a : A) :
    (TensorProduct.assoc R A A A).symm (comul.lTensor A (comul a)) = comul.rTensor A (comul a) := by
rw [(TensorProduct.assoc R A A A).symm_apply_eq, coassoc_apply a]
```

-- snippet 3
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.coassoc_symm (L105-L109)
theorem coassoc_symm :
    (TensorProduct.assoc R A A A).symm ∘ₗ comul.lTensor A ∘ₗ comul =
    comul.rTensor A ∘ₗ (comul (R := R)) :=
LinearMap.ext coassoc_symm_apply
```

-- snippet 4
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.lTensor_counit_comul (L115-L117)
theorem lTensor_counit_comul (a : A) : counit.lTensor A (comul a) = a ⊗ₜ[R] 1 :=
LinearMap.congr_fun lTensor_counit_comp_comul a
```

-- snippet 5
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_counit_tmul_eq (L119-L122)
lemma sum_counit_tmul_eq {a : A} (repr : Coalgebra.Repr R a) :
    ∑ i ∈ repr.index, counit (R := R) (repr.left i) ⊗ₜ (repr.right i) = 1 ⊗ₜ[R] a := by
simpa [← repr.eq, map_sum] using congr($(rTensor_counit_comp_comul (R := R) (A := A)) a)
```

-- snippet 6
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_tmul_counit_eq (L124-L128)
lemma sum_tmul_counit_eq {a : A} (repr : Coalgebra.Repr R a) :
    ∑ i ∈ repr.index, (repr.left i) ⊗ₜ counit (R := R) (repr.right i) = a ⊗ₜ[R] 1 := by
simpa [← repr.eq, map_sum] using congr($(lTensor_counit_comp_comul (R := R) (A := A)) a)

-- Cannot be @[simp] because `a₂` cannot be inferred by `simp`.
```

-- snippet 7
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_tmul_tmul_eq (L129-L137)
lemma sum_tmul_tmul_eq {a : A} (repr : Repr R a)
    (a₁ : (i : repr.ι) → Repr R (repr.left i)) (a₂ : (i : repr.ι) → Repr R (repr.right i)) :
    ∑ i ∈ repr.index, ∑ j ∈ (a₁ i).index,
      (a₁ i).left j ⊗ₜ[R] ((a₁ i).right j ⊗ₜ[R] repr.right i)
      = ∑ i ∈ repr.index, ∑ j ∈ (a₂ i).index,
      repr.left i ⊗ₜ[R] ((a₂ i).left j ⊗ₜ[R] (a₂ i).right j) := by
simpa [(a₂ _).eq, ← (a₁ _).eq, ← TensorProduct.tmul_sum,
    TensorProduct.sum_tmul, ← repr.eq] using congr($(coassoc (R := R)) a)
```

-- snippet 8
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_counit_tmul_map_eq (L139-L145)
theorem sum_counit_tmul_map_eq {B : Type*} [AddCommMonoid B] [Module R B]
    {F : Type*} [FunLike F A B] [LinearMapClass F R A B] (f : F) (a : A) {repr : Repr R a} :
    ∑ i ∈ repr.index, counit (R := R) (repr.left i) ⊗ₜ f (repr.right i) = 1 ⊗ₜ[R] f a := by
have := sum_counit_tmul_eq repr
  apply_fun LinearMap.lTensor R (f : A →ₗ[R] B) at this
  simp_all only [map_sum, LinearMap.lTensor_tmul, LinearMap.coe_coe]
```

-- snippet 9
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_map_tmul_counit_eq (L147-L154)
theorem sum_map_tmul_counit_eq {B : Type*} [AddCommMonoid B] [Module R B]
    {F : Type*} [FunLike F A B] [LinearMapClass F R A B] (f : F) (a : A) {repr : Repr R a} :
    ∑ i ∈ repr.index, f (repr.left i) ⊗ₜ counit (R := R) (repr.right i) = f a ⊗ₜ[R] 1 := by
have := sum_tmul_counit_eq repr
  apply_fun LinearMap.rTensor R (f : A →ₗ[R] B) at this
  simp_all only [map_sum, LinearMap.rTensor_tmul, LinearMap.coe_coe]

-- Cannot be @[simp] because `a₁` cannot be inferred by `simp`.
```

-- snippet 10
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_map_tmul_tmul_eq (L155-L166)
theorem sum_map_tmul_tmul_eq {B : Type*} [AddCommMonoid B] [Module R B]
    {F : Type*} [FunLike F A B] [LinearMapClass F R A B] (f g h : F) (a : A) {repr : Repr R a}
    {a₁ : (i : repr.ι) → Repr R (repr.left i)} {a₂ : (i : repr.ι) → Repr R (repr.right i)} :
    ∑ i ∈ repr.index, ∑ j ∈ (a₂ i).index,
      f (repr.left i) ⊗ₜ (g ((a₂ i).left j) ⊗ₜ h ((a₂ i).right j)) =
    ∑ i ∈ repr.index, ∑ j ∈ (a₁ i).index,
      f ((a₁ i).left j) ⊗ₜ[R] (g ((a₁ i).right j) ⊗ₜ[R] h (repr.right i)) := by
have := sum_tmul_tmul_eq repr a₁ a₂
  apply_fun TensorProduct.map (f : A →ₗ[R] B)
    (TensorProduct.map (g : A →ₗ[R] B) (h : A →ₗ[R] B)) at this
  simp_all only [map_sum, TensorProduct.map_tmul, LinearMap.coe_coe]
```

-- snippet 11
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.sum_counit_smul (L167-L171)
lemma sum_counit_smul (𝓡 : Repr R a) :
    ∑ x ∈ 𝓡.index, counit (R := R) (𝓡.left x) • 𝓡.right x = a := by
simpa only [map_sum, TensorProduct.lift.tmul, LinearMap.lsmul_apply, one_smul]
    using congr(TensorProduct.lift (LinearMap.lsmul R A) $(sum_counit_tmul_eq (R := R) 𝓡))
```

-- snippet 12
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.lift_lsmul_comp_counit_comp_comul (L172-L189)
lemma lift_lsmul_comp_counit_comp_comul :
    TensorProduct.lift (.lsmul R A ∘ₗ counit) ∘ₗ comul = .id := by
have := rTensor_counit_comp_comul (R := R) (A := A)
  apply_fun (TensorProduct.lift (LinearMap.lsmul R A) ∘ₗ ·) at this
  rw [LinearMap.rTensor, ← LinearMap.comp_assoc, TensorProduct.lift_comp_map, LinearMap.compl₂_id]
    at this
  ext
  simp [this]

variable (R A) in
/-- A coalgebra `A` is cocommutative if its comultiplication `δ : A → A ⊗ A` commutes with the
swapping `β : A ⊗ A ≃ A ⊗ A` of the factors in the tensor product. -/
class IsCocomm where
  protected comm_comp_comul : (TensorProduct.comm R A A).comp comul = comul

variable [IsCocomm R A]

variable (R A) in
```

-- snippet 13
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.toCoalgebra (L205-L211)
instance toCoalgebra : Coalgebra R R where
  comul := (TensorProduct.mk R R R) 1
counit := .id
  coassoc := rfl
  rTensor_counit_comp_comul := by ext; rfl
  lTensor_counit_comp_comul := by ext; rfl
```

-- snippet 14
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.comul_apply (L213-L214)
theorem comul_apply (r : R) : comul r = 1 ⊗ₜ[R] r := rfl
```

-- snippet 15
```lean
-- Mathlib.RingTheory.Coalgebra.Basic.counit_apply (L216-L217)
theorem counit_apply (r : R) : counit r = r := rfl
```

-- snippet 16
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgEquiv (L58-L61)
def toCoalgEquiv [EquivLike F A B] [CoalgEquivClass F R A B] (f : F) : A ≃ₗc[R] B :=
{ (f : A →ₗc[R] B), (f : A ≃ₗ[R] B) with }

/-- Reinterpret an element of a type of coalgebra equivalences as a coalgebra equivalence. -/
```

-- snippet 17
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgHom_inj (L110-L112)
theorem toCoalgHom_inj {e₁ e₂ : A ≃ₗc[R] B} : (↑e₁ : A →ₗc[R] B) = e₂ ↔ e₁ = e₂ :=
toCoalgHom_injective.eq_iff
```

-- snippet 18
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convNonUnitalSemiring (L123-L144)
instance convNonUnitalSemiring : NonUnitalSemiring (WithConv (C →ₗ[R] A)) where
  mul_assoc f g h := toConv_injective.eq_iff.mpr <| calc
_ = (μ ∘ₗ rTensor _ μ) ∘ₗ (((f.ofConv ⊗ₘ g.ofConv) ⊗ₘ h.ofConv) ∘ₗ
        (TensorProduct.assoc R C C C).symm) ∘ₗ lTensor C δ ∘ₗ δ := by
      ext; simp [comp_assoc, coassoc_symm, convMul_def]
    _ = (μ ∘ₗ rTensor A μ ∘ₗ ↑(TensorProduct.assoc R A A A).symm) ∘ₗ
        (f.ofConv ⊗ₘ (g.ofConv ⊗ₘ h.ofConv)) ∘ₗ lTensor C δ ∘ₗ δ := by
      simp only [map_map_comp_assoc_symm_eq, comp_assoc]
    _ = (μ ∘ₗ .lTensor _ μ) ∘ₗ (f.ofConv ⊗ₘ (g.ofConv ⊗ₘ h.ofConv)) ∘ₗ (lTensor C δ ∘ₗ δ) := by
      congr 1
      ext
      simp [mul_assoc]
    _ = μ ∘ₗ (f.ofConv ⊗ₘ μ ∘ₗ (g.ofConv ⊗ₘ h.ofConv) ∘ₗ δ) ∘ₗ δ := by ext; simp

end NonUnitalSemiring

section NonUnitalRing
variable [NonUnitalRing A] [AddCommMonoid C] [Module R A] [SMulCommClass R A A]
  [IsScalarTower R A A] [Module R C] [Coalgebra R C]

/-- Non-unital convolution ring structure on linear maps from a coalgebra to a
non-unital algebra. -/
```

-- snippet 19
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_coe (L127-L129)
theorem coe_coe : ⇑(e : A →ₗc[R] B) = e :=
rfl
```

-- snippet 20
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_toLinearEquiv (L139-L141)
theorem coe_toLinearEquiv : ⇑(e : A ≃ₗ[R] B) = e :=
rfl
```

-- snippet 21
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul_comp_coalgHom_distrib (L115-L122)
lemma convMul_comp_coalgHom_distrib [AddCommMonoid B] [Module R B] [CoalgebraStruct R B]
    (f g : WithConv (C →ₗ[R] A)) (h : B →ₗc[R] C) :
    (f * g).ofConv.comp h.toLinearMap =
      (toConv (f.ofConv.comp h.toLinearMap) * toConv (g.ofConv.comp h.toLinearMap)).ofConv := by
simp [convMul_def, map_comp, comp_assoc]

/-- Non-unital convolution semiring structure on linear maps from a coalgebra to a
non-unital algebra. -/
```

-- snippet 22
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul_apply (L62-L64)
lemma convMul_apply (f g : WithConv (C →ₗ[R] A)) (c : C) :
    (f * g) c = mul' R A (.map f.ofConv g.ofConv (comul c)) := rfl
```

-- snippet 23
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul (L55-L57)
instance convMul : Mul (WithConv (C →ₗ[R] A)) where
  mul f g := toConv (mul' R A ∘ₗ map f.ofConv g.ofConv ∘ₗ comul)
```

-- snippet 24
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_toCoalgHom (L143-L145)
theorem coe_toCoalgHom : ⇑(e : A →ₗc[R] B) = e :=
rfl
```

-- snippet 25
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convOne (L165-L166)
instance convOne : One (WithConv (C →ₗ[R] A)) where one := toConv (Algebra.linearMap R A ∘ₗ counit)
```

-- snippet 26
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.instCoeToCoalgEquiv (L62-L71)
instance instCoeToCoalgEquiv
    [EquivLike F A B] [CoalgEquivClass F R A B] : CoeHead F (A ≃ₗc[R] B) where
  coe f := toCoalgEquiv f
end CoalgEquivClass

namespace CoalgEquiv

variable [CommSemiring R]
```

-- snippet 27
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgHom_eq_coe (L135-L137)
theorem toCoalgHom_eq_coe (f : A ≃ₗc[R] B) : f.toCoalgHom = f :=
rfl
```

-- snippet 28
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.algHom_comp_convMul_distrib (L155-L164)
lemma algHom_comp_convMul_distrib (h : A →ₐ B) (f g : WithConv (C →ₗ[R] A)) :
    h.toLinearMap.comp (f * g).ofConv =
      (toConv (h.toLinearMap.comp f.ofConv) * toConv (h.toLinearMap.comp g.ofConv)).ofConv := by
simp [convMul_def, map_comp, ← comp_assoc, AlgHom.comp_mul']

end CoalgebraStruct

variable [Coalgebra R C]

/-- Convolution unit on linear maps from a coalgebra to an algebra. -/
```

-- snippet 29
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convNonUnitalNonAssocSemiring (L71-L76)
instance convNonUnitalNonAssocSemiring : NonUnitalNonAssocSemiring (WithConv (C →ₗ[R] A)) where
  left_distrib f g h := by ext; simp [map_add_right]
right_distrib f g h := by ext; simp [map_add_left]
  zero_mul f := by ext; simp
  mul_zero f := by ext; simp
```

-- snippet 30
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toLinearEquiv_eq_coe (L131-L133)
theorem toLinearEquiv_eq_coe (f : A ≃ₗc[R] B) : f.toLinearEquiv = f :=
rfl
```

-- snippet 31
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convOne_def (L167-L168)
lemma convOne_def : (1 : WithConv (C →ₗ[R] A)) = toConv (Algebra.linearMap R A ∘ₗ counit) := rfl
```

-- snippet 32
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convMul_def (L58-L60)
lemma convMul_def (f g : WithConv (C →ₗ[R] A)) :
    f * g = toConv (mul' R A ∘ₗ map f.ofConv g.ofConv ∘ₗ comul) := rfl
```

-- snippet 33
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.coe_mk (L114-L116)
theorem coe_mk {f h h₀ h₁ h₂ h₃ h₄ h₅} :
    (⟨⟨⟨⟨f, h⟩, h₀⟩, h₁, h₂⟩, h₃, h₄, h₅⟩ : A ≃ₗc[R] B) = f := rfl
```

-- snippet 34
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toEquiv_inj (L86-L88)
theorem toEquiv_inj {e₁ e₂ : A ≃ₗc[R] B} : e₁.toEquiv = e₂.toEquiv ↔ e₁ = e₂ :=
toEquiv_injective.eq_iff
```

-- snippet 35
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.nonUnitalAlgHom_comp_convMul_distrib (L108-L114)
lemma nonUnitalAlgHom_comp_convMul_distrib
    [NonUnitalNonAssocSemiring B] [Module R B] [SMulCommClass R B B] [IsScalarTower R B B]
    (h : A →ₙₐ[R] B) (f g : WithConv (C →ₗ[R] A)) :
    (h : A →ₗ[R] B).comp (f * g).ofConv =
      (toConv ((h : A →ₗ[R] B).comp f.ofConv) * toConv ((h : A →ₗ[R] B).comp g.ofConv)).ofConv := by
simp [convMul_def, map_comp, ← comp_assoc, NonUnitalAlgHom.comp_mul']
```

-- snippet 36
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convSemiring (L173-L184)
instance convSemiring : Semiring (WithConv (C →ₗ[R] A)) where
  one_mul f := by ext; simp [convOne_def, ← map_comp_rTensor]
mul_one f := by ext; simp [convOne_def, ← map_comp_lTensor]

end Semiring

section CommSemiring
variable [CommSemiring A] [AddCommMonoid C] [Algebra R A] [Module R C] [Coalgebra R C]
  [IsCocomm R C]

/-- Commutative convolution semiring structure on linear maps from a cocommutative coalgebra to an
algebra. -/
```

-- snippet 37
```lean
-- Mathlib.RingTheory.Coalgebra.Convolution.convCommSemiring (L185-L193)
instance convCommSemiring : CommSemiring (WithConv (C →ₗ[R] A)) where
  mul_comm f g := by ext x; rw [convMul_apply, ← comm_comul R x, map_comm, mul'_comm, convMul_apply]
end CommSemiring

section Ring
variable [Ring A] [AddCommMonoid C] [Algebra R A] [Module R C] [Coalgebra R C]

/-- Convolution ring structure on linear maps from a coalgebra to an algebra. -/
```

-- snippet 38
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toEquiv_injective (L80-L84)
theorem toEquiv_injective : Function.Injective (toEquiv : (A ≃ₗc[R] B) → A ≃ B) :=
fun ⟨_, _, _, _⟩ ⟨_, _, _, _⟩ h =>
    (CoalgEquiv.mk.injEq _ _ _ _ _ _ _ _).mpr
      ⟨CoalgHom.ext (congr_fun (Equiv.mk.inj h).1), (Equiv.mk.inj h).2⟩
```

-- snippet 39
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toEquiv (L78-L79)
def toEquiv : (A ≃ₗc[R] B) → A ≃ B := fun f => f.toLinearEquiv.toEquiv
```

-- snippet 40
```lean
-- Mathlib.RingTheory.Coalgebra.Equiv.toCoalgHom_injective (L89-L91)
theorem toCoalgHom_injective : Function.Injective (toCoalgHom : (A ≃ₗc[R] B) → A →ₗc[R] B) :=
fun _ _ H => toEquiv_injective <| Equiv.ext <| CoalgHom.congr_fun H
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Algebra.Vertex.VertexOperator).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem ext (A B : VertexOperator R V) (h : ∀ v : V, A v = B v) :
    A = B
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.VertexOperator (L39-L45)
abbrev VertexOperator (R : Type*) (V : Type*) [CommRing R] [AddCommGroup V]
    [Module R V] := HVertexOperator ℤ R V V
namespace VertexOperator

open HVertexOperator
```

-- snippet 2
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff (L51-L55)
def ncoeff : VertexOperator R V →ₗ[R] ℤ → Module.End R V where
  toFun A n := HVertexOperator.coeff A (-n - 1)
map_add' _ _ := by ext; simp
  map_smul' _ _ := by ext; simp
```

-- snippet 3
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff_apply (L56-L62)
theorem ncoeff_apply (A : VertexOperator R V) (n : ℤ) : ncoeff A n = coeff A (-n - 1) :=
rfl

/-- In the literature, the `n`th normalized coefficient of a vertex operator `A` is written as
either `Aₙ` or `A(n)`. -/
scoped[VertexOperator] notation A "[[" n "]]" => ncoeff A n
```

-- snippet 4
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.coeff_eq_ncoeff (L64-L67)
theorem coeff_eq_ncoeff (A : VertexOperator R V)
    (n : ℤ) : HVertexOperator.coeff A n = A[[-n - 1]] := by
rw [ncoeff_apply, neg_sub, Int.sub_neg, add_sub_cancel_left]
```

-- snippet 5
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff_eq_zero_of_lt_order (L68-L72)
theorem ncoeff_eq_zero_of_lt_order (A : VertexOperator R V) (n : ℤ) (x : V)
    (h : -n - 1 < HahnSeries.order ((HahnModule.of R).symm (A x))) : (A[[n]]) x = 0 := by
simp only [ncoeff, HVertexOperator.coeff, LinearMap.coe_mk, AddHom.coe_mk]
  exact HahnSeries.coeff_eq_zero_of_lt_order h
```

-- snippet 6
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.coeff_eq_zero_of_lt_order (L73-L83)
theorem coeff_eq_zero_of_lt_order (A : VertexOperator R V) (n : ℤ) (x : V)
    (h : n < HahnSeries.order ((HahnModule.of R).symm (A x))) : coeff A n x = 0 := by
rw [coeff_eq_ncoeff, ncoeff_eq_zero_of_lt_order A (-n - 1) x]
  lia

/-- Given an endomorphism-valued function on integers satisfying a pointwise bounded-pole condition,
we produce a vertex operator. -/
noncomputable def of_coeff (f : ℤ → Module.End R V)
    (hf : ∀ x, BddBelow (Function.support fun y ↦ f y x)) : VertexOperator R V :=
  HVertexOperator.of_coeff f fun x ↦ (BddBelow.isWF (hf x)).isPWO
```

-- snippet 7
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.of_coeff_apply_coeff (L85-L89)
theorem of_coeff_apply_coeff (f : ℤ → Module.End R V)
    (hf : ∀ x, BddBelow (Function.support fun y ↦ f y x)) (x : V) (n : ℤ) :
    ((HahnModule.of R).symm ((of_coeff f hf) x)).coeff n = (f n) x := by
rfl
```

-- snippet 8
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff_of_coeff (L91-L97)
theorem ncoeff_of_coeff (f : ℤ → Module.End R V)
    (hf : ∀ x, BddBelow (Function.support fun y ↦ f y x)) (n : ℤ) :
    (of_coeff f hf)[[n]] = f (-n - 1) := by
ext v
  rw [ncoeff_apply, coeff_apply_apply, of_coeff_apply_coeff]

end VertexOperator
```

-- snippet 9
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.comp (L138-L148)
def comp : HVertexOperator (Γ' ×ₗ Γ) R U W where
  toFun u := HahnModule.of R (HahnSeries.ofIterate (compHahnSeries A B u))
map_add' := by
    intro u v
    ext g
    simp [HahnSeries.ofIterate]
  map_smul' := by
    intro r x
    ext g
    simp [HahnSeries.ofIterate]
```

-- snippet 10
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.compHahnSeries_add (L121-L127)
theorem compHahnSeries_add (u v : U) :
    compHahnSeries A B (u + v) = compHahnSeries A B u + compHahnSeries A B v := by
ext
  simp only [compHahnSeries_coeff, map_add, coeff_apply_apply, HahnSeries.coeff_add', Pi.add_apply]
  rw [← HahnSeries.coeff_add]

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 11
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.compHahnSeries_smul (L129-L136)
theorem compHahnSeries_smul (r : R) (u : U) :
    compHahnSeries A B (r • u) = r • compHahnSeries A B u := by
ext
  simp only [compHahnSeries_coeff, map_smul, coeff_apply_apply, HahnSeries.coeff_smul]
  rw [← HahnSeries.coeff_smul]

set_option backward.isDefEq.respectTransparency false in
/-- The composite of two heterogeneous vertex operators, as a heterogeneous vertex operator. -/
```

-- snippet 12
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_of_coeff (L89-L92)
theorem coeff_of_coeff (f : Γ → V →ₗ[R] W)
    (hf : ∀ (x : V), (Function.support (fun g => f g x)).IsPWO) : (of_coeff f hf).coeff = f :=
rfl
```

-- snippet 13
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.of_coeff_coeff (L94-L109)
theorem of_coeff_coeff (A : HVertexOperator Γ R V W) : of_coeff A.coeff A.coeff_isPWOsupport = A :=
rfl

end Coeff

section Products

variable {Γ Γ' : Type*} [PartialOrder Γ] [PartialOrder Γ'] {R : Type*}
  [CommRing R] {U V W : Type*} [AddCommGroup U] [Module R U] [AddCommGroup V] [Module R V]
  [AddCommGroup W] [Module R W] (A : HVertexOperator Γ R V W) (B : HVertexOperator Γ' R U V)

open HahnModule

set_option backward.isDefEq.respectTransparency false in
/-- The composite of two heterogeneous vertex operators acting on a vector, as an iterated Hahn
series. -/
```

-- snippet 14
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.HVertexOperator (L42-L51)
abbrev HVertexOperator (Γ : Type*) [PartialOrder Γ] (R : Type*) [CommRing R]
    (V : Type*) (W : Type*) [AddCommGroup V] [Module R V] [AddCommGroup W] [Module R W] :=
V →ₗ[R] (HahnModule Γ R W)

namespace HVertexOperator

section Coeff

open HahnModule
```

-- snippet 15
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_comp (L150-L156)
theorem coeff_comp (g : Γ' ×ₗ Γ) :
    (comp A B).coeff g = A.coeff (ofLex g).2 ∘ₗ B.coeff (ofLex g).1 := by
rfl

end Products

end HVertexOperator
```

-- snippet 16
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.compHahnSeries (L111-L119)
def compHahnSeries (u : U) : HahnSeries Γ' (HahnSeries Γ W) where
  coeff g' := A (coeff B g' u)
isPWO_support' := by
    refine Set.IsPWO.mono (((of R).symm (B u)).isPWO_support') ?_
    simp only [coeff_apply_apply, Function.support_subset_iff, ne_eq, Function.mem_support]
    intro g' hg' hAB
    exact hg' (by simp [hAB])

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 17
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_isPWOsupport (L68-L71)
theorem coeff_isPWOsupport (A : HVertexOperator Γ R V W) (v : V) :
    ((of R).symm (A v)).coeff.support.IsPWO :=
((of R).symm (A v)).isPWO_support'
```

-- snippet 18
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.of_coeff (L82-L87)
def of_coeff (f : Γ → V →ₗ[R] W) (hf : ∀ (x : V), (Function.support (f · x)).IsPWO) :
    HVertexOperator Γ R V W where
  toFun x := (of R) { coeff := fun g => f g x, isPWO_support' := hf x }
map_add' _ _ := by ext; simp
  map_smul' _ _ := by ext; simp
```

-- snippet 19
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_inj (L73-L80)
theorem coeff_inj : Function.Injective (coeff : HVertexOperator Γ R V W →ₗ[R] Γ → (V →ₗ[R] W)) := by
intro _ _ h
  ext v n
  exact congrFun (congrArg DFunLike.coe (congrFun h n)) v

set_option backward.isDefEq.respectTransparency false in
/-- Given a coefficient function valued in linear maps satisfying a partially well-ordered support
condition, we produce a heterogeneous vertex operator. -/
```

-- snippet 20
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff (L60-L67)
def coeff : HVertexOperator Γ R V W →ₗ[R] Γ → V →ₗ[R] W where
  toFun A n := {
toFun v := ((of R).symm (A v)).coeff n
    map_add' u v := by simp
    map_smul' r v := by simp }
  map_add' _ _ := by ext; simp
  map_smul' _ _ := by ext; simp
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Algebra.Vertex.VertexOperator).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem ext (A B : VertexOperator R V) (h : ∀ v : V, A v = B v) :
    A = B
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.VertexOperator (L39-L45)
abbrev VertexOperator (R : Type*) (V : Type*) [CommRing R] [AddCommGroup V]
    [Module R V] := HVertexOperator ℤ R V V
namespace VertexOperator

open HVertexOperator
```

-- snippet 2
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff (L51-L55)
def ncoeff : VertexOperator R V →ₗ[R] ℤ → Module.End R V where
  toFun A n := HVertexOperator.coeff A (-n - 1)
map_add' _ _ := by ext; simp
  map_smul' _ _ := by ext; simp
```

-- snippet 3
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff_apply (L56-L62)
theorem ncoeff_apply (A : VertexOperator R V) (n : ℤ) : ncoeff A n = coeff A (-n - 1) :=
rfl

/-- In the literature, the `n`th normalized coefficient of a vertex operator `A` is written as
either `Aₙ` or `A(n)`. -/
scoped[VertexOperator] notation A "[[" n "]]" => ncoeff A n
```

-- snippet 4
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.coeff_eq_ncoeff (L64-L67)
theorem coeff_eq_ncoeff (A : VertexOperator R V)
    (n : ℤ) : HVertexOperator.coeff A n = A[[-n - 1]] := by
rw [ncoeff_apply, neg_sub, Int.sub_neg, add_sub_cancel_left]
```

-- snippet 5
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff_eq_zero_of_lt_order (L68-L72)
theorem ncoeff_eq_zero_of_lt_order (A : VertexOperator R V) (n : ℤ) (x : V)
    (h : -n - 1 < HahnSeries.order ((HahnModule.of R).symm (A x))) : (A[[n]]) x = 0 := by
simp only [ncoeff, HVertexOperator.coeff, LinearMap.coe_mk, AddHom.coe_mk]
  exact HahnSeries.coeff_eq_zero_of_lt_order h
```

-- snippet 6
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.coeff_eq_zero_of_lt_order (L73-L83)
theorem coeff_eq_zero_of_lt_order (A : VertexOperator R V) (n : ℤ) (x : V)
    (h : n < HahnSeries.order ((HahnModule.of R).symm (A x))) : coeff A n x = 0 := by
rw [coeff_eq_ncoeff, ncoeff_eq_zero_of_lt_order A (-n - 1) x]
  lia

/-- Given an endomorphism-valued function on integers satisfying a pointwise bounded-pole condition,
we produce a vertex operator. -/
noncomputable def of_coeff (f : ℤ → Module.End R V)
    (hf : ∀ x, BddBelow (Function.support fun y ↦ f y x)) : VertexOperator R V :=
  HVertexOperator.of_coeff f fun x ↦ (BddBelow.isWF (hf x)).isPWO
```

-- snippet 7
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.of_coeff_apply_coeff (L85-L89)
theorem of_coeff_apply_coeff (f : ℤ → Module.End R V)
    (hf : ∀ x, BddBelow (Function.support fun y ↦ f y x)) (x : V) (n : ℤ) :
    ((HahnModule.of R).symm ((of_coeff f hf) x)).coeff n = (f n) x := by
rfl
```

-- snippet 8
```lean
-- Mathlib.Algebra.Vertex.VertexOperator.ncoeff_of_coeff (L91-L97)
theorem ncoeff_of_coeff (f : ℤ → Module.End R V)
    (hf : ∀ x, BddBelow (Function.support fun y ↦ f y x)) (n : ℤ) :
    (of_coeff f hf)[[n]] = f (-n - 1) := by
ext v
  rw [ncoeff_apply, coeff_apply_apply, of_coeff_apply_coeff]

end VertexOperator
```

-- snippet 9
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.comp (L138-L148)
def comp : HVertexOperator (Γ' ×ₗ Γ) R U W where
  toFun u := HahnModule.of R (HahnSeries.ofIterate (compHahnSeries A B u))
map_add' := by
    intro u v
    ext g
    simp [HahnSeries.ofIterate]
  map_smul' := by
    intro r x
    ext g
    simp [HahnSeries.ofIterate]
```

-- snippet 10
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.compHahnSeries_add (L121-L127)
theorem compHahnSeries_add (u v : U) :
    compHahnSeries A B (u + v) = compHahnSeries A B u + compHahnSeries A B v := by
ext
  simp only [compHahnSeries_coeff, map_add, coeff_apply_apply, HahnSeries.coeff_add', Pi.add_apply]
  rw [← HahnSeries.coeff_add]

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 11
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.compHahnSeries_smul (L129-L136)
theorem compHahnSeries_smul (r : R) (u : U) :
    compHahnSeries A B (r • u) = r • compHahnSeries A B u := by
ext
  simp only [compHahnSeries_coeff, map_smul, coeff_apply_apply, HahnSeries.coeff_smul]
  rw [← HahnSeries.coeff_smul]

set_option backward.isDefEq.respectTransparency false in
/-- The composite of two heterogeneous vertex operators, as a heterogeneous vertex operator. -/
```

-- snippet 12
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_of_coeff (L89-L92)
theorem coeff_of_coeff (f : Γ → V →ₗ[R] W)
    (hf : ∀ (x : V), (Function.support (fun g => f g x)).IsPWO) : (of_coeff f hf).coeff = f :=
rfl
```

-- snippet 13
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.of_coeff_coeff (L94-L109)
theorem of_coeff_coeff (A : HVertexOperator Γ R V W) : of_coeff A.coeff A.coeff_isPWOsupport = A :=
rfl

end Coeff

section Products

variable {Γ Γ' : Type*} [PartialOrder Γ] [PartialOrder Γ'] {R : Type*}
  [CommRing R] {U V W : Type*} [AddCommGroup U] [Module R U] [AddCommGroup V] [Module R V]
  [AddCommGroup W] [Module R W] (A : HVertexOperator Γ R V W) (B : HVertexOperator Γ' R U V)

open HahnModule

set_option backward.isDefEq.respectTransparency false in
/-- The composite of two heterogeneous vertex operators acting on a vector, as an iterated Hahn
series. -/
```

-- snippet 14
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.HVertexOperator (L42-L51)
abbrev HVertexOperator (Γ : Type*) [PartialOrder Γ] (R : Type*) [CommRing R]
    (V : Type*) (W : Type*) [AddCommGroup V] [Module R V] [AddCommGroup W] [Module R W] :=
V →ₗ[R] (HahnModule Γ R W)

namespace HVertexOperator

section Coeff

open HahnModule
```

-- snippet 15
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_comp (L150-L156)
theorem coeff_comp (g : Γ' ×ₗ Γ) :
    (comp A B).coeff g = A.coeff (ofLex g).2 ∘ₗ B.coeff (ofLex g).1 := by
rfl

end Products

end HVertexOperator
```

-- snippet 16
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.compHahnSeries (L111-L119)
def compHahnSeries (u : U) : HahnSeries Γ' (HahnSeries Γ W) where
  coeff g' := A (coeff B g' u)
isPWO_support' := by
    refine Set.IsPWO.mono (((of R).symm (B u)).isPWO_support') ?_
    simp only [coeff_apply_apply, Function.support_subset_iff, ne_eq, Function.mem_support]
    intro g' hg' hAB
    exact hg' (by simp [hAB])

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 17
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_isPWOsupport (L68-L71)
theorem coeff_isPWOsupport (A : HVertexOperator Γ R V W) (v : V) :
    ((of R).symm (A v)).coeff.support.IsPWO :=
((of R).symm (A v)).isPWO_support'
```

-- snippet 18
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.of_coeff (L82-L87)
def of_coeff (f : Γ → V →ₗ[R] W) (hf : ∀ (x : V), (Function.support (f · x)).IsPWO) :
    HVertexOperator Γ R V W where
  toFun x := (of R) { coeff := fun g => f g x, isPWO_support' := hf x }
map_add' _ _ := by ext; simp
  map_smul' _ _ := by ext; simp
```

-- snippet 19
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff_inj (L73-L80)
theorem coeff_inj : Function.Injective (coeff : HVertexOperator Γ R V W →ₗ[R] Γ → (V →ₗ[R] W)) := by
intro _ _ h
  ext v n
  exact congrFun (congrArg DFunLike.coe (congrFun h n)) v

set_option backward.isDefEq.respectTransparency false in
/-- Given a coefficient function valued in linear maps satisfying a partially well-ordered support
condition, we produce a heterogeneous vertex operator. -/
```

-- snippet 20
```lean
-- Mathlib.Algebra.Vertex.HVertexOperator.coeff (L60-L67)
def coeff : HVertexOperator Γ R V W →ₗ[R] Γ → V →ₗ[R] W where
  toFun A n := {
toFun v := ((of R).symm (A v)).coeff n
    map_add' u v := by simp
    map_smul' r v := by simp }
  map_add' _ _ := by ext; simp
  map_smul' _ _ := by ext; simp
```
[/INST]

mistral-common:Tekken v15 (Mistral chat template, [INST]/[SYSTEM_PROMPT])


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Algebra.Polynomial.Laurent).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
def trunc : R[T;T⁻¹] →+ R[X]
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Polynomial.Laurent.LaurentPolynomial (L84-L86)
abbrev LaurentPolynomial (R : Type*) [Semiring R] :=
AddMonoidAlgebra R ℤ
```

-- snippet 2
```lean
-- Mathlib.Algebra.Polynomial.Laurent.LaurentPolynomial (L93-L97)
theorem LaurentPolynomial.ext [Semiring R] {p q : R[T;T⁻¹]} (h : ∀ a, p a = q a) : p = q :=
Finsupp.ext h

/-- The ring homomorphism, taking a polynomial with coefficients in `R` to a Laurent polynomial
with coefficients in `R`. -/
```

-- snippet 3
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L98-L102)
def Polynomial.toLaurent [Semiring R] : R[X] →+* R[T;T⁻¹] :=
(mapDomainRingHom R Int.ofNatHom).comp (toFinsuppIso R).toRingHom

/-- This is not a simp lemma, as it is usually preferable to use the lemmas about `C` and `X`
instead. -/
```

-- snippet 4
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L103-L108)
theorem Polynomial.toLaurent_apply [Semiring R] (p : R[X]) :
    toLaurent p = p.toFinsupp.mapDomain (↑) :=
rfl

/-- The `R`-algebra map, taking a polynomial with coefficients in `R` to a Laurent polynomial
with coefficients in `R`. -/
```

-- snippet 5
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L109-L111)
def Polynomial.toLaurentAlg [CommSemiring R] : R[X] →ₐ[R] R[T;T⁻¹] :=
(mapDomainAlgHom R R Int.ofNatHom).comp (toFinsuppIsoAlg R).toAlgHom
```

-- snippet 6
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L116-L124)
theorem Polynomial.toLaurentAlg_apply [CommSemiring R] (f : R[X]) : toLaurentAlg f = toLaurent f :=
rfl

namespace LaurentPolynomial

section Semiring

variable [Semiring R]
```

-- snippet 7
```lean
-- Mathlib.Algebra.Polynomial.Laurent.single_zero_one_eq_one (L125-L131)
theorem single_zero_one_eq_one : (.single 0 1 : R[T;T⁻¹]) = (1 : R[T;T⁻¹]) :=
rfl

/-!  ### The functions `C` and `T`. -/

/-- The ring homomorphism `C`, including `R` into the ring of Laurent polynomials over `R` as
the constant Laurent polynomials. -/
```

-- snippet 8
```lean
-- Mathlib.Algebra.Polynomial.Laurent.C (L132-L134)
def C : R →+* R[T;T⁻¹] :=
singleZeroRingHom
```

-- snippet 9
```lean
-- Mathlib.Algebra.Polynomial.Laurent.algebraMap_apply (L135-L142)
theorem algebraMap_apply {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (r : R) :
    algebraMap R (LaurentPolynomial A) r = C (algebraMap R A r) :=
rfl

/-- When we have `[CommSemiring R]`, the function `C` is the same as `algebraMap R R[T;T⁻¹]`.
(But note that `C` is defined when `R` is not necessarily commutative, in which case
`algebraMap` is not available.)
-/
```

-- snippet 10
```lean
-- Mathlib.Algebra.Polynomial.Laurent.C_eq_algebraMap (L143-L145)
theorem C_eq_algebraMap {R : Type*} [CommSemiring R] (r : R) : C r = algebraMap R R[T;T⁻¹] r :=
rfl
```

-- snippet 11
```lean
-- Mathlib.Algebra.Polynomial.Laurent.single_eq_C (L146-L147)
theorem single_eq_C (r : R) : .single 0 r = C r := rfl
```

-- snippet 12
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T (L156-L158)
def T (n : ℤ) : R[T;T⁻¹] :=
.single n 1
```

-- snippet 13
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T_zero (L163-L165)
theorem T_zero : (T 0 : R[T;T⁻¹]) = 1 :=
rfl
```

-- snippet 14
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T_add (L166-L168)
theorem T_add (m n : ℤ) : (T (m + n) : R[T;T⁻¹]) = T m * T n := by
simp [T, single_mul_single]
```

-- snippet 15
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T_sub (L169-L170)
theorem T_sub (m n : ℤ) : (T (m - n) : R[T;T⁻¹]) = T m * T (-n) := by rw [← T_add, sub_eq_add_neg]
```

-- snippet 16
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_eq_eval₂AlgHom_CAlgHom (L189-L192)
theorem mapAlgHom_eq_eval₂AlgHom_CAlgHom (f : A →ₐ[R] B) : mapAlgHom f = eval₂AlgHom
    (CAlgHom.comp f) X (fun a => (commute_X (C (f a))).symm) := by
rfl
```

-- snippet 17
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.lcoeff_comp_mapAlgHom_eq (L197-L201)
lemma lcoeff_comp_mapAlgHom_eq (f : A →ₐ[R] B) (n : ℕ) :
    (lcoeff B n).restrictScalars R ∘ₗ (mapAlgHom f).toLinearMap =
      f.toLinearMap ∘ₗ (lcoeff A n).restrictScalars R := by
ext f; simp
```

-- snippet 18
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.CAlgHom (L95-L100)
def CAlgHom : A →ₐ[R] A[X] where
  toRingHom := C
commutes' _ := rfl

/-- Extensionality lemma for algebra maps out of `A'[X]` over a smaller base ring than `A'`
-/
```

-- snippet 19
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.subalgebraNontrivial (L117-L127)
instance subalgebraNontrivial [Nontrivial A] : Nontrivial (Subalgebra R A[X]) :=
⟨⟨⊥, ⊤, by
      rw [Ne, SetLike.ext_iff, not_forall]
      refine ⟨X, ?_⟩
      simp only [Algebra.mem_bot, not_exists, Set.mem_range, iff_true, Algebra.mem_top,
        algebraMap_apply]
      intro x
      rw [ext_iff, not_forall]
      refine ⟨1, ?_⟩
      simp⟩⟩
```

-- snippet 20
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.toFinsupp_algebraMap (L73-L77)
theorem toFinsupp_algebraMap (r : R) : (algebraMap R A[X] r).toFinsupp = algebraMap R _ r :=
show toFinsupp (C (algebraMap _ _ r)) = _ by
    rw [toFinsupp_C]
    rfl
```

-- snippet 21
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom (L167-L170)
def mapAlgHom (f : A →ₐ[R] B) : Polynomial A →ₐ[R] Polynomial B where
  toRingHom := mapRingHom f.toRingHom
commutes' := by simp
```

-- snippet 22
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.ringHom_eval₂_intCastRingHom (L145-L148)
theorem ringHom_eval₂_intCastRingHom {R S : Type*} [Ring R] [Ring S] (p : ℤ[X]) (f : R →+* S)
    (r : R) : f (eval₂ (Int.castRingHom R) r p) = eval₂ (Int.castRingHom S) (f r) p :=
algHom_eval₂_algebraMap p f.toIntAlgHom r
```

-- snippet 23
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.eval₂_intCastRingHom_X (L150-L156)
theorem eval₂_intCastRingHom_X {R : Type*} [Ring R] (p : ℤ[X]) (f : ℤ[X] →+* R) :
    eval₂ (Int.castRingHom R) (f X) p = f p :=
eval₂_algebraMap_X p f.toIntAlgHom

/-- `Polynomial.eval₂` as an `AlgHom` for noncommutative algebras.

This is `Polynomial.eval₂RingHom'` for `AlgHom`s. -/
```

-- snippet 24
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.eval₂_algebraMap_X (L136-L143)
theorem eval₂_algebraMap_X {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (p : R[X])
    (f : R[X] →ₐ[R] A) : eval₂ (algebraMap R A) (f X) p = f p := by
conv_rhs => rw [← Polynomial.sum_C_mul_X_pow_eq p]
  simp only [eval₂_eq_sum, sum_def]
  simp only [map_sum, map_mul, map_pow]
  simp [Polynomial.C_eq_algebraMap]

-- these used to be about `algebraMap ℤ R`, but now the simp-normal form is `Int.castRingHom R`.
```

-- snippet 25
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algebraMap_apply (L69-L71)
theorem algebraMap_apply (r : R) : algebraMap R A[X] r = C (algebraMap R A r) :=
rfl
```

-- snippet 26
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgEquiv (L206-L208)
def mapAlgEquiv (f : A ≃ₐ[R] B) : Polynomial A ≃ₐ[R] Polynomial B :=
AlgEquiv.ofAlgHom (mapAlgHom f.toAlgHom) (mapAlgHom f.symm.toAlgHom) (by simp) (by simp)
```

-- snippet 27
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_monomial (L202-L205)
lemma mapAlgHom_monomial (f : A →ₐ[R] B) (n : ℕ) (a : A) :
    mapAlgHom f (monomial n a) = monomial n (f a) := by simp
/-- If `A` and `B` are isomorphic as `R`-algebras, then so are their polynomial rings -/
```

-- snippet 28
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_id (L176-L178)
theorem mapAlgHom_id : mapAlgHom (AlgHom.id R A) = AlgHom.id R (Polynomial A) :=
AlgHom.ext fun _x => map_id
```

-- snippet 29
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algebraMap_eq (L90-L93)
theorem algebraMap_eq : algebraMap R R[X] = C :=
rfl

/-- `Polynomial.C` as an `AlgHom`. -/
```

-- snippet 30
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.eval₂AlgHom (L158-L166)
def eval₂AlgHom (f : A →ₐ[R] B) (b : B) (hf : ∀ a, Commute (f a) b) : A[X] →ₐ[R] B where
  toRingHom := eval₂RingHom' f b hf
commutes' _ := (eval₂_C _ _).trans (f.commutes _)

section Map

/-- `Polynomial.map` as an `AlgHom` for noncommutative algebras.

  This is the algebra version of `Polynomial.mapRingHom`. -/
```

-- snippet 31
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_coe_ringHom (L180-L183)
theorem mapAlgHom_coe_ringHom (f : A →ₐ[R] B) :
    ↑(mapAlgHom f : _ →ₐ[R] Polynomial B) = (mapRingHom ↑f : Polynomial A →+* Polynomial B) :=
rfl
```

-- snippet 32
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.C_eq_algebraMap (L86-L88)
theorem C_eq_algebraMap (r : R) : C r = algebraMap R R[X] r :=
rfl
```

-- snippet 33
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.ofFinsupp_algebraMap (L78-L85)
theorem ofFinsupp_algebraMap (r : R) : (⟨algebraMap R _ r⟩ : A[X]) = algebraMap R A[X] r :=
toFinsupp_injective (toFinsupp_algebraMap _).symm

/-- When we have `[CommSemiring R]`, the function `C` is the same as `algebraMap R R[X]`.

(But note that `C` is defined when `R` is not necessarily commutative, in which case
`algebraMap` is not available.)
-/
```

-- snippet 34
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algHom_ext' (L102-L110)
theorem algHom_ext' {f g : A[X] →ₐ[R] B}
    (hC : f.comp CAlgHom = g.comp CAlgHom)
    (hX : f X = g X) : f = g :=
AlgHom.coe_ringHom_injective (ringHom_ext' (congr_arg AlgHom.toRingHom hC) hX)

variable (R) in
open AddMonoidAlgebra in
/-- Algebra isomorphism between `R[X]` and `R[ℕ]`. This is just an
implementation detail, but it can be useful to transfer results from `Finsupp` to polynomials. -/
```

-- snippet 35
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_comp (L185-L188)
theorem mapAlgHom_comp (C : Type*) [Semiring C] [Algebra R C] (f : B →ₐ[R] C) (g : A →ₐ[R] B) :
    (mapAlgHom f).comp (mapAlgHom g) = mapAlgHom (f.comp g) := by
ext <;> simp
```

-- snippet 36
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.coeff_mapAlgHom_apply (L193-L196)
lemma coeff_mapAlgHom_apply (f : A →ₐ[R] B) (p : A[X]) (n : ℕ) :
    coeff (mapAlgHom f p) n = f (coeff p n) := by
simp
```

-- snippet 37
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.coe_mapAlgHom (L172-L174)
theorem coe_mapAlgHom (f : A →ₐ[R] B) : ⇑(mapAlgHom f) = map f :=
rfl
```

-- snippet 38
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.toFinsuppIsoAlg (L112-L116)
def toFinsuppIsoAlg : R[X] ≃ₐ[R] R[ℕ] :=
{ toFinsuppIso R with
    commutes' := fun r => by
      dsimp }
```

-- snippet 39
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algHom_eval₂_algebraMap (L129-L134)
theorem algHom_eval₂_algebraMap {R A B : Type*} [CommSemiring R] [Semiring A] [Semiring B]
    [Algebra R A] [Algebra R B] (p : R[X]) (f : A →ₐ[R] B) (a : A) :
    f (eval₂ (algebraMap R A) a p) = eval₂ (algebraMap R B) (f a) p := by
simp only [eval₂_eq_sum, sum_def]
  simp only [map_sum, map_mul, map_pow, AlgHom.commutes]
```

-- snippet 40
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algebraOfAlgebra (L55-L67)
instance algebraOfAlgebra : Algebra R A[X] where
  smul_def' r p :=
toFinsupp_injective <| by
      dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply]
      rw [toFinsupp_smul, toFinsupp_mul, toFinsupp_C]
      exact Algebra.smul_def' _ _
  commutes' r p :=
    toFinsupp_injective <| by
      dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply]
      simp_rw [toFinsupp_mul, toFinsupp_C]
      convert Algebra.commutes' r p.toFinsupp
  algebraMap := C.comp (algebraMap R A)
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Algebra.Polynomial.Laurent).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
def trunc : R[T;T⁻¹] →+ R[X]
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Polynomial.Laurent.LaurentPolynomial (L84-L86)
abbrev LaurentPolynomial (R : Type*) [Semiring R] :=
AddMonoidAlgebra R ℤ
```

-- snippet 2
```lean
-- Mathlib.Algebra.Polynomial.Laurent.LaurentPolynomial (L93-L97)
theorem LaurentPolynomial.ext [Semiring R] {p q : R[T;T⁻¹]} (h : ∀ a, p a = q a) : p = q :=
Finsupp.ext h

/-- The ring homomorphism, taking a polynomial with coefficients in `R` to a Laurent polynomial
with coefficients in `R`. -/
```

-- snippet 3
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L98-L102)
def Polynomial.toLaurent [Semiring R] : R[X] →+* R[T;T⁻¹] :=
(mapDomainRingHom R Int.ofNatHom).comp (toFinsuppIso R).toRingHom

/-- This is not a simp lemma, as it is usually preferable to use the lemmas about `C` and `X`
instead. -/
```

-- snippet 4
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L103-L108)
theorem Polynomial.toLaurent_apply [Semiring R] (p : R[X]) :
    toLaurent p = p.toFinsupp.mapDomain (↑) :=
rfl

/-- The `R`-algebra map, taking a polynomial with coefficients in `R` to a Laurent polynomial
with coefficients in `R`. -/
```

-- snippet 5
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L109-L111)
def Polynomial.toLaurentAlg [CommSemiring R] : R[X] →ₐ[R] R[T;T⁻¹] :=
(mapDomainAlgHom R R Int.ofNatHom).comp (toFinsuppIsoAlg R).toAlgHom
```

-- snippet 6
```lean
-- Mathlib.Algebra.Polynomial.Laurent.Polynomial (L116-L124)
theorem Polynomial.toLaurentAlg_apply [CommSemiring R] (f : R[X]) : toLaurentAlg f = toLaurent f :=
rfl

namespace LaurentPolynomial

section Semiring

variable [Semiring R]
```

-- snippet 7
```lean
-- Mathlib.Algebra.Polynomial.Laurent.single_zero_one_eq_one (L125-L131)
theorem single_zero_one_eq_one : (.single 0 1 : R[T;T⁻¹]) = (1 : R[T;T⁻¹]) :=
rfl

/-!  ### The functions `C` and `T`. -/

/-- The ring homomorphism `C`, including `R` into the ring of Laurent polynomials over `R` as
the constant Laurent polynomials. -/
```

-- snippet 8
```lean
-- Mathlib.Algebra.Polynomial.Laurent.C (L132-L134)
def C : R →+* R[T;T⁻¹] :=
singleZeroRingHom
```

-- snippet 9
```lean
-- Mathlib.Algebra.Polynomial.Laurent.algebraMap_apply (L135-L142)
theorem algebraMap_apply {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (r : R) :
    algebraMap R (LaurentPolynomial A) r = C (algebraMap R A r) :=
rfl

/-- When we have `[CommSemiring R]`, the function `C` is the same as `algebraMap R R[T;T⁻¹]`.
(But note that `C` is defined when `R` is not necessarily commutative, in which case
`algebraMap` is not available.)
-/
```

-- snippet 10
```lean
-- Mathlib.Algebra.Polynomial.Laurent.C_eq_algebraMap (L143-L145)
theorem C_eq_algebraMap {R : Type*} [CommSemiring R] (r : R) : C r = algebraMap R R[T;T⁻¹] r :=
rfl
```

-- snippet 11
```lean
-- Mathlib.Algebra.Polynomial.Laurent.single_eq_C (L146-L147)
theorem single_eq_C (r : R) : .single 0 r = C r := rfl
```

-- snippet 12
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T (L156-L158)
def T (n : ℤ) : R[T;T⁻¹] :=
.single n 1
```

-- snippet 13
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T_zero (L163-L165)
theorem T_zero : (T 0 : R[T;T⁻¹]) = 1 :=
rfl
```

-- snippet 14
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T_add (L166-L168)
theorem T_add (m n : ℤ) : (T (m + n) : R[T;T⁻¹]) = T m * T n := by
simp [T, single_mul_single]
```

-- snippet 15
```lean
-- Mathlib.Algebra.Polynomial.Laurent.T_sub (L169-L170)
theorem T_sub (m n : ℤ) : (T (m - n) : R[T;T⁻¹]) = T m * T (-n) := by rw [← T_add, sub_eq_add_neg]
```

-- snippet 16
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_eq_eval₂AlgHom_CAlgHom (L189-L192)
theorem mapAlgHom_eq_eval₂AlgHom_CAlgHom (f : A →ₐ[R] B) : mapAlgHom f = eval₂AlgHom
    (CAlgHom.comp f) X (fun a => (commute_X (C (f a))).symm) := by
rfl
```

-- snippet 17
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.lcoeff_comp_mapAlgHom_eq (L197-L201)
lemma lcoeff_comp_mapAlgHom_eq (f : A →ₐ[R] B) (n : ℕ) :
    (lcoeff B n).restrictScalars R ∘ₗ (mapAlgHom f).toLinearMap =
      f.toLinearMap ∘ₗ (lcoeff A n).restrictScalars R := by
ext f; simp
```

-- snippet 18
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.CAlgHom (L95-L100)
def CAlgHom : A →ₐ[R] A[X] where
  toRingHom := C
commutes' _ := rfl

/-- Extensionality lemma for algebra maps out of `A'[X]` over a smaller base ring than `A'`
-/
```

-- snippet 19
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.subalgebraNontrivial (L117-L127)
instance subalgebraNontrivial [Nontrivial A] : Nontrivial (Subalgebra R A[X]) :=
⟨⟨⊥, ⊤, by
      rw [Ne, SetLike.ext_iff, not_forall]
      refine ⟨X, ?_⟩
      simp only [Algebra.mem_bot, not_exists, Set.mem_range, iff_true, Algebra.mem_top,
        algebraMap_apply]
      intro x
      rw [ext_iff, not_forall]
      refine ⟨1, ?_⟩
      simp⟩⟩
```

-- snippet 20
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.toFinsupp_algebraMap (L73-L77)
theorem toFinsupp_algebraMap (r : R) : (algebraMap R A[X] r).toFinsupp = algebraMap R _ r :=
show toFinsupp (C (algebraMap _ _ r)) = _ by
    rw [toFinsupp_C]
    rfl
```

-- snippet 21
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom (L167-L170)
def mapAlgHom (f : A →ₐ[R] B) : Polynomial A →ₐ[R] Polynomial B where
  toRingHom := mapRingHom f.toRingHom
commutes' := by simp
```

-- snippet 22
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.ringHom_eval₂_intCastRingHom (L145-L148)
theorem ringHom_eval₂_intCastRingHom {R S : Type*} [Ring R] [Ring S] (p : ℤ[X]) (f : R →+* S)
    (r : R) : f (eval₂ (Int.castRingHom R) r p) = eval₂ (Int.castRingHom S) (f r) p :=
algHom_eval₂_algebraMap p f.toIntAlgHom r
```

-- snippet 23
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.eval₂_intCastRingHom_X (L150-L156)
theorem eval₂_intCastRingHom_X {R : Type*} [Ring R] (p : ℤ[X]) (f : ℤ[X] →+* R) :
    eval₂ (Int.castRingHom R) (f X) p = f p :=
eval₂_algebraMap_X p f.toIntAlgHom

/-- `Polynomial.eval₂` as an `AlgHom` for noncommutative algebras.

This is `Polynomial.eval₂RingHom'` for `AlgHom`s. -/
```

-- snippet 24
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.eval₂_algebraMap_X (L136-L143)
theorem eval₂_algebraMap_X {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (p : R[X])
    (f : R[X] →ₐ[R] A) : eval₂ (algebraMap R A) (f X) p = f p := by
conv_rhs => rw [← Polynomial.sum_C_mul_X_pow_eq p]
  simp only [eval₂_eq_sum, sum_def]
  simp only [map_sum, map_mul, map_pow]
  simp [Polynomial.C_eq_algebraMap]

-- these used to be about `algebraMap ℤ R`, but now the simp-normal form is `Int.castRingHom R`.
```

-- snippet 25
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algebraMap_apply (L69-L71)
theorem algebraMap_apply (r : R) : algebraMap R A[X] r = C (algebraMap R A r) :=
rfl
```

-- snippet 26
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgEquiv (L206-L208)
def mapAlgEquiv (f : A ≃ₐ[R] B) : Polynomial A ≃ₐ[R] Polynomial B :=
AlgEquiv.ofAlgHom (mapAlgHom f.toAlgHom) (mapAlgHom f.symm.toAlgHom) (by simp) (by simp)
```

-- snippet 27
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_monomial (L202-L205)
lemma mapAlgHom_monomial (f : A →ₐ[R] B) (n : ℕ) (a : A) :
    mapAlgHom f (monomial n a) = monomial n (f a) := by simp
/-- If `A` and `B` are isomorphic as `R`-algebras, then so are their polynomial rings -/
```

-- snippet 28
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_id (L176-L178)
theorem mapAlgHom_id : mapAlgHom (AlgHom.id R A) = AlgHom.id R (Polynomial A) :=
AlgHom.ext fun _x => map_id
```

-- snippet 29
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algebraMap_eq (L90-L93)
theorem algebraMap_eq : algebraMap R R[X] = C :=
rfl

/-- `Polynomial.C` as an `AlgHom`. -/
```

-- snippet 30
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.eval₂AlgHom (L158-L166)
def eval₂AlgHom (f : A →ₐ[R] B) (b : B) (hf : ∀ a, Commute (f a) b) : A[X] →ₐ[R] B where
  toRingHom := eval₂RingHom' f b hf
commutes' _ := (eval₂_C _ _).trans (f.commutes _)

section Map

/-- `Polynomial.map` as an `AlgHom` for noncommutative algebras.

  This is the algebra version of `Polynomial.mapRingHom`. -/
```

-- snippet 31
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_coe_ringHom (L180-L183)
theorem mapAlgHom_coe_ringHom (f : A →ₐ[R] B) :
    ↑(mapAlgHom f : _ →ₐ[R] Polynomial B) = (mapRingHom ↑f : Polynomial A →+* Polynomial B) :=
rfl
```

-- snippet 32
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.C_eq_algebraMap (L86-L88)
theorem C_eq_algebraMap (r : R) : C r = algebraMap R R[X] r :=
rfl
```

-- snippet 33
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.ofFinsupp_algebraMap (L78-L85)
theorem ofFinsupp_algebraMap (r : R) : (⟨algebraMap R _ r⟩ : A[X]) = algebraMap R A[X] r :=
toFinsupp_injective (toFinsupp_algebraMap _).symm

/-- When we have `[CommSemiring R]`, the function `C` is the same as `algebraMap R R[X]`.

(But note that `C` is defined when `R` is not necessarily commutative, in which case
`algebraMap` is not available.)
-/
```

-- snippet 34
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algHom_ext' (L102-L110)
theorem algHom_ext' {f g : A[X] →ₐ[R] B}
    (hC : f.comp CAlgHom = g.comp CAlgHom)
    (hX : f X = g X) : f = g :=
AlgHom.coe_ringHom_injective (ringHom_ext' (congr_arg AlgHom.toRingHom hC) hX)

variable (R) in
open AddMonoidAlgebra in
/-- Algebra isomorphism between `R[X]` and `R[ℕ]`. This is just an
implementation detail, but it can be useful to transfer results from `Finsupp` to polynomials. -/
```

-- snippet 35
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.mapAlgHom_comp (L185-L188)
theorem mapAlgHom_comp (C : Type*) [Semiring C] [Algebra R C] (f : B →ₐ[R] C) (g : A →ₐ[R] B) :
    (mapAlgHom f).comp (mapAlgHom g) = mapAlgHom (f.comp g) := by
ext <;> simp
```

-- snippet 36
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.coeff_mapAlgHom_apply (L193-L196)
lemma coeff_mapAlgHom_apply (f : A →ₐ[R] B) (p : A[X]) (n : ℕ) :
    coeff (mapAlgHom f p) n = f (coeff p n) := by
simp
```

-- snippet 37
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.coe_mapAlgHom (L172-L174)
theorem coe_mapAlgHom (f : A →ₐ[R] B) : ⇑(mapAlgHom f) = map f :=
rfl
```

-- snippet 38
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.toFinsuppIsoAlg (L112-L116)
def toFinsuppIsoAlg : R[X] ≃ₐ[R] R[ℕ] :=
{ toFinsuppIso R with
    commutes' := fun r => by
      dsimp }
```

-- snippet 39
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algHom_eval₂_algebraMap (L129-L134)
theorem algHom_eval₂_algebraMap {R A B : Type*} [CommSemiring R] [Semiring A] [Semiring B]
    [Algebra R A] [Algebra R B] (p : R[X]) (f : A →ₐ[R] B) (a : A) :
    f (eval₂ (algebraMap R A) a p) = eval₂ (algebraMap R B) (f a) p := by
simp only [eval₂_eq_sum, sum_def]
  simp only [map_sum, map_mul, map_pow, AlgHom.commutes]
```

-- snippet 40
```lean
-- Mathlib.Algebra.Polynomial.AlgebraMap.algebraOfAlgebra (L55-L67)
instance algebraOfAlgebra : Algebra R A[X] where
  smul_def' r p :=
toFinsupp_injective <| by
      dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply]
      rw [toFinsupp_smul, toFinsupp_mul, toFinsupp_C]
      exact Algebra.smul_def' _ _
  commutes' r p :=
    toFinsupp_injective <| by
      dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply]
      simp_rw [toFinsupp_mul, toFinsupp_C]
      convert Algebra.commutes' r p.toFinsupp
  algebraMap := C.comp (algebraMap R A)
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Data.PNat.Xgcd).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
def gcdB' : ℕ+
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Data.PNat.Xgcd.mk' (L79-L82)
def mk' (w : ℕ+) (x : ℕ) (y : ℕ) (z : ℕ+) (a : ℕ+) (b : ℕ+) : XgcdType :=
mk w.val.pred x y z.val.pred a.val.pred b.val.pred

/-- `w = wp + 1` -/
```

-- snippet 2
```lean
-- Mathlib.Data.PNat.Xgcd.w (L83-L86)
def w : ℕ+ :=
succPNat u.wp

/-- `z = zp + 1` -/
```

-- snippet 3
```lean
-- Mathlib.Data.PNat.Xgcd.z (L87-L90)
def z : ℕ+ :=
succPNat u.zp

/-- `a = ap + 1` -/
```

-- snippet 4
```lean
-- Mathlib.Data.PNat.Xgcd.a (L91-L94)
def a : ℕ+ :=
succPNat u.ap

/-- `b = bp + 1` -/
```

-- snippet 5
```lean
-- Mathlib.Data.PNat.Xgcd.b (L95-L98)
def b : ℕ+ :=
succPNat u.bp

/-- `r = a % b`: remainder -/
```

-- snippet 6
```lean
-- Mathlib.Data.PNat.Xgcd.r (L99-L102)
def r : ℕ :=
(u.ap + 1) % (u.bp + 1)

/-- `q = ap / bp`: quotient -/
```

-- snippet 7
```lean
-- Mathlib.Data.PNat.Xgcd.q (L103-L106)
def q : ℕ :=
(u.ap + 1) / (u.bp + 1)

/-- `qp = q - 1` -/
```

-- snippet 8
```lean
-- Mathlib.Data.PNat.Xgcd.qp (L107-L114)
def qp : ℕ :=
u.q - 1

/-- The map `v` gives the product of the matrix
`[[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]`
and the vector `[a, b] = [ap + 1, bp + 1]`.  The map
`vp` gives `[sp, tp]` such that `v = [sp + 1, tp + 1]`.
-/
```

-- snippet 9
```lean
-- Mathlib.Data.PNat.Xgcd.vp (L115-L118)
def vp : ℕ × ℕ :=
⟨u.wp + u.x + u.ap + u.wp * u.ap + u.x * u.bp, u.y + u.zp + u.bp + u.y * u.ap + u.zp * u.bp⟩

/-- `v = [sp + 1, tp + 1]`, check `vp` -/
```

-- snippet 10
```lean
-- Mathlib.Data.PNat.Xgcd.v (L119-L122)
def v : ℕ × ℕ :=
⟨u.w * u.a + u.x * u.b, u.y * u.a + u.z * u.b⟩

/-- `succ₂ [t.1, t.2] = [t.1.succ, t.2.succ]` -/
```

-- snippet 11
```lean
-- Mathlib.Data.PNat.Xgcd.succ₂ (L123-L125)
def succ₂ (t : ℕ × ℕ) : ℕ × ℕ :=
⟨t.1.succ, t.2.succ⟩
```

-- snippet 12
```lean
-- Mathlib.Data.PNat.Xgcd.v_eq_succ_vp (L126-L129)
theorem v_eq_succ_vp : u.v = succ₂ u.vp := by
ext <;> dsimp [v, vp, w, z, a, b, succ₂] <;> ring_nf

/-- `IsSpecial` holds if the matrix has determinant one. -/
```

-- snippet 13
```lean
-- Mathlib.Data.PNat.Xgcd.IsSpecial (L130-L133)
def IsSpecial : Prop :=
u.wp + u.zp + u.wp * u.zp = u.x * u.y

/-- `IsSpecial'` is an alternative of `IsSpecial`. -/
```

-- snippet 14
```lean
-- Mathlib.Data.PNat.Xgcd.IsSpecial' (L134-L136)
def IsSpecial' : Prop :=
u.w * u.z = succPNat (u.x * u.y)
```

-- snippet 15
```lean
-- Mathlib.Data.PNat.Xgcd.isSpecial_iff (L137-L150)
theorem isSpecial_iff : u.IsSpecial ↔ u.IsSpecial' := by
dsimp [IsSpecial, IsSpecial']
  let ⟨wp, x, y, zp, ap, bp⟩ := u
  constructor <;> intro h <;> simp only [w, succPNat, succ_eq_add_one, z] at * <;>
    simp only [← coe_inj, mul_coe, mk_coe] at *
  · simp_all [← h]; ring
  · simp only [Nat.mul_add, Nat.add_mul, one_mul, mul_one, ← Nat.add_assoc,
      Nat.add_right_cancel_iff] at h
    rw [← h]; ring

/-- `IsReduced` holds if the two entries in the vector are the
same.  The reduction algorithm will produce a system with this
property, whose product vector is the same as for the original
system. -/
```

-- snippet 16
```lean
-- Mathlib.Data.PNat.Basic.succPNat_lt_succPNat (L84-L86)
theorem succPNat_lt_succPNat {m n : ℕ} : m.succPNat < n.succPNat ↔ m < n :=
succPNat_strictMono.lt_iff_lt
```

-- snippet 17
```lean
-- Mathlib.Data.PNat.Basic.natPred_inj (L59-L61)
theorem natPred_inj {m n : ℕ+} : m.natPred = n.natPred ↔ m = n :=
natPred_injective.eq_iff
```

-- snippet 18
```lean
-- Mathlib.Data.PNat.Basic.coeAddHom (L119-L124)
def coeAddHom : AddHom ℕ+ ℕ where
  toFun := (↑)
map_add' := add_coe

/-- The order isomorphism between ℕ and ℕ+ given by `succ`. -/
```

-- snippet 19
```lean
-- Mathlib.Data.PNat.Basic.natPred_le_natPred (L55-L57)
theorem natPred_le_natPred {m n : ℕ+} : m.natPred ≤ n.natPred ↔ m ≤ n :=
natPred_strictMono.le_iff_le
```

-- snippet 20
```lean
-- Mathlib.Data.PNat.Basic.one_add_natPred (L33-L35)
theorem one_add_natPred (n : ℕ+) : 1 + n.natPred = n := by
rw [natPred, add_tsub_cancel_iff_le.mpr <| show 1 ≤ (n : ℕ) from n.2]
```

-- snippet 21
```lean
-- Mathlib.Data.PNat.Basic.succPNat_le_succPNat (L88-L90)
theorem succPNat_le_succPNat {m n : ℕ} : m.succPNat ≤ n.succPNat ↔ m ≤ n :=
succPNat_strictMono.le_iff_le
```

-- snippet 22
```lean
-- Mathlib.Data.PNat.Basic.succPNat_injective (L91-L93)
theorem succPNat_injective : Function.Injective succPNat :=
succPNat_strictMono.injective
```

-- snippet 23
```lean
-- Mathlib.Data.PNat.Basic.add_one_le_iff (L136-L137)
theorem add_one_le_iff : ∀ {a b : ℕ+}, a + 1 ≤ b ↔ a < b := Nat.add_one_le_iff
```

-- snippet 24
```lean
-- Mathlib.Data.PNat.Basic.coe_inj (L110-L112)
theorem coe_inj {m n : ℕ+} : (m : ℕ) = n ↔ m = n :=
Subtype.ext_iff.symm
```

-- snippet 25
```lean
-- Mathlib.Data.PNat.Basic.instOrderBot (L138-L141)
instance instOrderBot : OrderBot ℕ+ where
  bot := 1
bot_le a := a.property
```

-- snippet 26
```lean
-- Mathlib.Data.PNat.Basic.natPred_monotone (L44-L46)
theorem natPred_monotone : Monotone natPred :=
natPred_strictMono.monotone
```

-- snippet 27
```lean
-- Mathlib.Data.PNat.Basic.natPred_injective (L47-L49)
theorem natPred_injective : Function.Injective natPred :=
natPred_strictMono.injective
```

-- snippet 28
```lean
-- Mathlib.Data.PNat.Basic.natPred_lt_natPred (L51-L53)
theorem natPred_lt_natPred {m n : ℕ+} : m.natPred < n.natPred ↔ m < n :=
natPred_strictMono.lt_iff_lt
```

-- snippet 29
```lean
-- Mathlib.Data.PNat.Basic.succPNat_strictMono (L77-L78)
theorem succPNat_strictMono : StrictMono succPNat := fun _ _ => Nat.succ_lt_succ
```

-- snippet 30
```lean
-- Mathlib.Data.PNat.Basic.natPred_add_one (L37-L39)
theorem natPred_add_one (n : ℕ+) : n.natPred + 1 = n :=
(add_comm _ _).trans n.one_add_natPred
```

-- snippet 31
```lean
-- Mathlib.Data.PNat.Basic.bot_eq_one (L143-L146)
theorem bot_eq_one : (⊥ : ℕ+) = 1 :=
rfl

/-- Strong induction on `ℕ+`, with `n = 1` treated separately. -/
```

-- snippet 32
```lean
-- Mathlib.Data.PNat.Basic.val_ofNat (L63-L66)
lemma val_ofNat (n : ℕ) [NeZero n] :
    ((ofNat(n) : ℕ+) : ℕ) = OfNat.ofNat n :=
rfl
```

-- snippet 33
```lean
-- Mathlib.Data.PNat.Basic.mk_ofNat (L68-L75)
lemma mk_ofNat (n : ℕ) (h : 0 < n) :
    @Eq ℕ+ (⟨ofNat(n), h⟩ : ℕ+) (haveI : NeZero n := ⟨h.ne'⟩; OfNat.ofNat n) :=
rfl

end PNat

namespace Nat
```

-- snippet 34
```lean
-- Mathlib.Data.PNat.Basic.recOn (L160-L168)
def recOn (n : ℕ+) {p : ℕ+ → Sort*} (one : p 1) (succ : ∀ n, p n → p (n + 1)) : p n := by
rcases n with ⟨n, h⟩
  induction n with
  | zero => exact absurd h (by decide)
  | succ n IH =>
    rcases n with - | n
    · exact one
    · exact succ _ (IH n.succ_pos)
```

-- snippet 35
```lean
-- Mathlib.Data.PNat.Basic.add_coe (L114-L117)
theorem add_coe (m n : ℕ+) : ((m + n : ℕ+) : ℕ) = m + n :=
rfl

/-- `coe` promoted to an `AddHom`, that is, a morphism which preserves addition. -/
```

-- snippet 36
```lean
-- Mathlib.Data.PNat.Basic.succPNat_mono (L80-L82)
theorem succPNat_mono : Monotone succPNat :=
succPNat_strictMono.monotone
```

-- snippet 37
```lean
-- Mathlib.Data.PNat.Basic.natPred_strictMono (L41-L42)
theorem natPred_strictMono : StrictMono natPred := fun m _ h => Nat.pred_lt_pred m.2.ne' h
```

-- snippet 38
```lean
-- Mathlib.Data.PNat.Basic.succPNat_inj (L95-L108)
theorem succPNat_inj {n m : ℕ} : succPNat n = succPNat m ↔ n = m :=
succPNat_injective.eq_iff

end Nat

namespace PNat

open Nat

/-- We now define a long list of structures on `ℕ+` induced by
similar structures on `ℕ`. Most of these behave in a completely
obvious way, but there are a few things to be said about
subtraction, division and powers.
-/
```

-- snippet 39
```lean
-- Mathlib.Data.PNat.Basic.caseStrongInductionOn (L147-L158)
def caseStrongInductionOn {p : ℕ+ → Sort*} (a : ℕ+) (hz : p 1)
    (hi : ∀ n, (∀ m, m ≤ n → p m) → p (n + 1)) : p a := by
apply strongInductionOn a
  rintro ⟨k, kprop⟩ hk
  rcases k with - | k
  · exact (lt_irrefl 0 kprop).elim
  rcases k with - | k
  · exact hz
  exact hi ⟨k.succ, Nat.succ_pos _⟩ fun m hm => hk _ (Nat.lt_succ_iff.2 hm)

/-- An induction principle for `ℕ+`: it takes values in `Sort*`, so it applies also to Types,
not only to `Prop`. -/
```

-- snippet 40
```lean
-- Mathlib.Data.PNat.Basic.lt_add_one_iff (L134-L135)
theorem lt_add_one_iff : ∀ {a b : ℕ+}, a < b + 1 ↔ a ≤ b := Nat.lt_add_one_iff
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Data.PNat.Xgcd).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
def gcdB' : ℕ+
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Data.PNat.Xgcd.mk' (L79-L82)
def mk' (w : ℕ+) (x : ℕ) (y : ℕ) (z : ℕ+) (a : ℕ+) (b : ℕ+) : XgcdType :=
mk w.val.pred x y z.val.pred a.val.pred b.val.pred

/-- `w = wp + 1` -/
```

-- snippet 2
```lean
-- Mathlib.Data.PNat.Xgcd.w (L83-L86)
def w : ℕ+ :=
succPNat u.wp

/-- `z = zp + 1` -/
```

-- snippet 3
```lean
-- Mathlib.Data.PNat.Xgcd.z (L87-L90)
def z : ℕ+ :=
succPNat u.zp

/-- `a = ap + 1` -/
```

-- snippet 4
```lean
-- Mathlib.Data.PNat.Xgcd.a (L91-L94)
def a : ℕ+ :=
succPNat u.ap

/-- `b = bp + 1` -/
```

-- snippet 5
```lean
-- Mathlib.Data.PNat.Xgcd.b (L95-L98)
def b : ℕ+ :=
succPNat u.bp

/-- `r = a % b`: remainder -/
```

-- snippet 6
```lean
-- Mathlib.Data.PNat.Xgcd.r (L99-L102)
def r : ℕ :=
(u.ap + 1) % (u.bp + 1)

/-- `q = ap / bp`: quotient -/
```

-- snippet 7
```lean
-- Mathlib.Data.PNat.Xgcd.q (L103-L106)
def q : ℕ :=
(u.ap + 1) / (u.bp + 1)

/-- `qp = q - 1` -/
```

-- snippet 8
```lean
-- Mathlib.Data.PNat.Xgcd.qp (L107-L114)
def qp : ℕ :=
u.q - 1

/-- The map `v` gives the product of the matrix
`[[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]`
and the vector `[a, b] = [ap + 1, bp + 1]`.  The map
`vp` gives `[sp, tp]` such that `v = [sp + 1, tp + 1]`.
-/
```

-- snippet 9
```lean
-- Mathlib.Data.PNat.Xgcd.vp (L115-L118)
def vp : ℕ × ℕ :=
⟨u.wp + u.x + u.ap + u.wp * u.ap + u.x * u.bp, u.y + u.zp + u.bp + u.y * u.ap + u.zp * u.bp⟩

/-- `v = [sp + 1, tp + 1]`, check `vp` -/
```

-- snippet 10
```lean
-- Mathlib.Data.PNat.Xgcd.v (L119-L122)
def v : ℕ × ℕ :=
⟨u.w * u.a + u.x * u.b, u.y * u.a + u.z * u.b⟩

/-- `succ₂ [t.1, t.2] = [t.1.succ, t.2.succ]` -/
```

-- snippet 11
```lean
-- Mathlib.Data.PNat.Xgcd.succ₂ (L123-L125)
def succ₂ (t : ℕ × ℕ) : ℕ × ℕ :=
⟨t.1.succ, t.2.succ⟩
```

-- snippet 12
```lean
-- Mathlib.Data.PNat.Xgcd.v_eq_succ_vp (L126-L129)
theorem v_eq_succ_vp : u.v = succ₂ u.vp := by
ext <;> dsimp [v, vp, w, z, a, b, succ₂] <;> ring_nf

/-- `IsSpecial` holds if the matrix has determinant one. -/
```

-- snippet 13
```lean
-- Mathlib.Data.PNat.Xgcd.IsSpecial (L130-L133)
def IsSpecial : Prop :=
u.wp + u.zp + u.wp * u.zp = u.x * u.y

/-- `IsSpecial'` is an alternative of `IsSpecial`. -/
```

-- snippet 14
```lean
-- Mathlib.Data.PNat.Xgcd.IsSpecial' (L134-L136)
def IsSpecial' : Prop :=
u.w * u.z = succPNat (u.x * u.y)
```

-- snippet 15
```lean
-- Mathlib.Data.PNat.Xgcd.isSpecial_iff (L137-L150)
theorem isSpecial_iff : u.IsSpecial ↔ u.IsSpecial' := by
dsimp [IsSpecial, IsSpecial']
  let ⟨wp, x, y, zp, ap, bp⟩ := u
  constructor <;> intro h <;> simp only [w, succPNat, succ_eq_add_one, z] at * <;>
    simp only [← coe_inj, mul_coe, mk_coe] at *
  · simp_all [← h]; ring
  · simp only [Nat.mul_add, Nat.add_mul, one_mul, mul_one, ← Nat.add_assoc,
      Nat.add_right_cancel_iff] at h
    rw [← h]; ring

/-- `IsReduced` holds if the two entries in the vector are the
same.  The reduction algorithm will produce a system with this
property, whose product vector is the same as for the original
system. -/
```

-- snippet 16
```lean
-- Mathlib.Data.PNat.Basic.succPNat_lt_succPNat (L84-L86)
theorem succPNat_lt_succPNat {m n : ℕ} : m.succPNat < n.succPNat ↔ m < n :=
succPNat_strictMono.lt_iff_lt
```

-- snippet 17
```lean
-- Mathlib.Data.PNat.Basic.natPred_inj (L59-L61)
theorem natPred_inj {m n : ℕ+} : m.natPred = n.natPred ↔ m = n :=
natPred_injective.eq_iff
```

-- snippet 18
```lean
-- Mathlib.Data.PNat.Basic.coeAddHom (L119-L124)
def coeAddHom : AddHom ℕ+ ℕ where
  toFun := (↑)
map_add' := add_coe

/-- The order isomorphism between ℕ and ℕ+ given by `succ`. -/
```

-- snippet 19
```lean
-- Mathlib.Data.PNat.Basic.natPred_le_natPred (L55-L57)
theorem natPred_le_natPred {m n : ℕ+} : m.natPred ≤ n.natPred ↔ m ≤ n :=
natPred_strictMono.le_iff_le
```

-- snippet 20
```lean
-- Mathlib.Data.PNat.Basic.one_add_natPred (L33-L35)
theorem one_add_natPred (n : ℕ+) : 1 + n.natPred = n := by
rw [natPred, add_tsub_cancel_iff_le.mpr <| show 1 ≤ (n : ℕ) from n.2]
```

-- snippet 21
```lean
-- Mathlib.Data.PNat.Basic.succPNat_le_succPNat (L88-L90)
theorem succPNat_le_succPNat {m n : ℕ} : m.succPNat ≤ n.succPNat ↔ m ≤ n :=
succPNat_strictMono.le_iff_le
```

-- snippet 22
```lean
-- Mathlib.Data.PNat.Basic.succPNat_injective (L91-L93)
theorem succPNat_injective : Function.Injective succPNat :=
succPNat_strictMono.injective
```

-- snippet 23
```lean
-- Mathlib.Data.PNat.Basic.add_one_le_iff (L136-L137)
theorem add_one_le_iff : ∀ {a b : ℕ+}, a + 1 ≤ b ↔ a < b := Nat.add_one_le_iff
```

-- snippet 24
```lean
-- Mathlib.Data.PNat.Basic.coe_inj (L110-L112)
theorem coe_inj {m n : ℕ+} : (m : ℕ) = n ↔ m = n :=
Subtype.ext_iff.symm
```

-- snippet 25
```lean
-- Mathlib.Data.PNat.Basic.instOrderBot (L138-L141)
instance instOrderBot : OrderBot ℕ+ where
  bot := 1
bot_le a := a.property
```

-- snippet 26
```lean
-- Mathlib.Data.PNat.Basic.natPred_monotone (L44-L46)
theorem natPred_monotone : Monotone natPred :=
natPred_strictMono.monotone
```

-- snippet 27
```lean
-- Mathlib.Data.PNat.Basic.natPred_injective (L47-L49)
theorem natPred_injective : Function.Injective natPred :=
natPred_strictMono.injective
```

-- snippet 28
```lean
-- Mathlib.Data.PNat.Basic.natPred_lt_natPred (L51-L53)
theorem natPred_lt_natPred {m n : ℕ+} : m.natPred < n.natPred ↔ m < n :=
natPred_strictMono.lt_iff_lt
```

-- snippet 29
```lean
-- Mathlib.Data.PNat.Basic.succPNat_strictMono (L77-L78)
theorem succPNat_strictMono : StrictMono succPNat := fun _ _ => Nat.succ_lt_succ
```

-- snippet 30
```lean
-- Mathlib.Data.PNat.Basic.natPred_add_one (L37-L39)
theorem natPred_add_one (n : ℕ+) : n.natPred + 1 = n :=
(add_comm _ _).trans n.one_add_natPred
```

-- snippet 31
```lean
-- Mathlib.Data.PNat.Basic.bot_eq_one (L143-L146)
theorem bot_eq_one : (⊥ : ℕ+) = 1 :=
rfl

/-- Strong induction on `ℕ+`, with `n = 1` treated separately. -/
```

-- snippet 32
```lean
-- Mathlib.Data.PNat.Basic.val_ofNat (L63-L66)
lemma val_ofNat (n : ℕ) [NeZero n] :
    ((ofNat(n) : ℕ+) : ℕ) = OfNat.ofNat n :=
rfl
```

-- snippet 33
```lean
-- Mathlib.Data.PNat.Basic.mk_ofNat (L68-L75)
lemma mk_ofNat (n : ℕ) (h : 0 < n) :
    @Eq ℕ+ (⟨ofNat(n), h⟩ : ℕ+) (haveI : NeZero n := ⟨h.ne'⟩; OfNat.ofNat n) :=
rfl

end PNat

namespace Nat
```

-- snippet 34
```lean
-- Mathlib.Data.PNat.Basic.recOn (L160-L168)
def recOn (n : ℕ+) {p : ℕ+ → Sort*} (one : p 1) (succ : ∀ n, p n → p (n + 1)) : p n := by
rcases n with ⟨n, h⟩
  induction n with
  | zero => exact absurd h (by decide)
  | succ n IH =>
    rcases n with - | n
    · exact one
    · exact succ _ (IH n.succ_pos)
```

-- snippet 35
```lean
-- Mathlib.Data.PNat.Basic.add_coe (L114-L117)
theorem add_coe (m n : ℕ+) : ((m + n : ℕ+) : ℕ) = m + n :=
rfl

/-- `coe` promoted to an `AddHom`, that is, a morphism which preserves addition. -/
```

-- snippet 36
```lean
-- Mathlib.Data.PNat.Basic.succPNat_mono (L80-L82)
theorem succPNat_mono : Monotone succPNat :=
succPNat_strictMono.monotone
```

-- snippet 37
```lean
-- Mathlib.Data.PNat.Basic.natPred_strictMono (L41-L42)
theorem natPred_strictMono : StrictMono natPred := fun m _ h => Nat.pred_lt_pred m.2.ne' h
```

-- snippet 38
```lean
-- Mathlib.Data.PNat.Basic.succPNat_inj (L95-L108)
theorem succPNat_inj {n m : ℕ} : succPNat n = succPNat m ↔ n = m :=
succPNat_injective.eq_iff

end Nat

namespace PNat

open Nat

/-- We now define a long list of structures on `ℕ+` induced by
similar structures on `ℕ`. Most of these behave in a completely
obvious way, but there are a few things to be said about
subtraction, division and powers.
-/
```

-- snippet 39
```lean
-- Mathlib.Data.PNat.Basic.caseStrongInductionOn (L147-L158)
def caseStrongInductionOn {p : ℕ+ → Sort*} (a : ℕ+) (hz : p 1)
    (hi : ∀ n, (∀ m, m ≤ n → p m) → p (n + 1)) : p a := by
apply strongInductionOn a
  rintro ⟨k, kprop⟩ hk
  rcases k with - | k
  · exact (lt_irrefl 0 kprop).elim
  rcases k with - | k
  · exact hz
  exact hi ⟨k.succ, Nat.succ_pos _⟩ fun m hm => hk _ (Nat.lt_succ_iff.2 hm)

/-- An induction principle for `ℕ+`: it takes values in `Sort*`, so it applies also to Types,
not only to `Prop`. -/
```

-- snippet 40
```lean
-- Mathlib.Data.PNat.Basic.lt_add_one_iff (L134-L135)
theorem lt_add_one_iff : ∀ {a b : ℕ+}, a < b + 1 ↔ a ≤ b := Nat.lt_add_one_iff
```
[/INST]