[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.LinearAlgebra.BilinearForm.Basic).

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

```lean
def coeFnAddMonoidHom : BilinForm R M →+ M → M → R where
  toFun
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_left (L65-L66)
theorem add_left (x y z : M) : B (x + y) z = B x z + B y z := map_add₂ _ _ _ _
```

-- snippet 2
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left (L67-L68)
theorem smul_left (a : R) (x y : M) : B (a • x) y = a * B x y := map_smul₂ _ _ _ _
```

-- snippet 3
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_right (L69-L70)
theorem add_right (x y z : M) : B x (y + z) = B x y + B x z := map_add _ _ _
```

-- snippet 4
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right (L71-L72)
theorem smul_right (a : R) (x y : M) : B x (a • y) = a * B x y := map_smul _ _ _
```

-- snippet 5
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_left (L73-L74)
theorem zero_left (x : M) : B 0 x = 0 := map_zero₂ _ _
```

-- snippet 6
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_right (L75-L76)
theorem zero_right (x : M) : B x 0 = 0 := map_zero _
```

-- snippet 7
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_left (L77-L78)
theorem neg_left (x y : M₁) : B₁ (-x) y = -B₁ x y := map_neg₂ _ _ _
```

-- snippet 8
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_right (L79-L80)
theorem neg_right (x y : M₁) : B₁ x (-y) = -B₁ x y := map_neg _ _
```

-- snippet 9
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_left (L81-L82)
theorem sub_left (x y z : M₁) : B₁ (x - y) z = B₁ x z - B₁ y z := map_sub₂ _ _ _ _
```

-- snippet 10
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_right (L83-L84)
theorem sub_right (x y z : M₁) : B₁ x (y - z) = B₁ x y - B₁ x z := map_sub _ _ _
```

-- snippet 11
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left_of_tower (L85-L87)
lemma smul_left_of_tower (r : S) (x y : M) : B (r • x) y = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_left, Algebra.smul_def]
```

-- snippet 12
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right_of_tower (L88-L93)
lemma smul_right_of_tower (r : S) (x y : M) : B x (r • y) = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_right, Algebra.smul_def]

variable {D : BilinForm R M} {D₁ : BilinForm R₁ M₁}

-- TODO: instantiate `FunLike`
```

-- snippet 13
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.coe_injective (L94-L98)
theorem coe_injective : Function.Injective ((fun B x y => B x y) : BilinForm R M → M → M → R) :=
fun B D h => by
    ext x y
    apply congrFun₂ h
```

-- snippet 14
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.ext (L100-L101)
theorem ext (H : ∀ x y : M, B x y = D x y) : B = D := ext₂ H
```

-- snippet 15
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.congr_fun (L102-L103)
theorem congr_fun (h : B = D) (x y : M) : B x y = D x y := congr_fun₂ h _ _
```

-- snippet 16
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleParing (L58-L60)
def dualSubmoduleParing {N : Submodule R M} (x : B.dualSubmodule N) (y : N) : R :=
(Submodule.mem_one.mp <| x.prop y y.prop).choose
```

-- snippet 17
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleParing_spec (L62-L67)
lemma dualSubmoduleParing_spec {N : Submodule R M} (x : B.dualSubmodule N) (y : N) :
    algebraMap R S (B.dualSubmoduleParing x y) = B x y :=
(Submodule.mem_one.mp <| x.prop y y.prop).choose_spec

/-- The natural paring of `B.dualSubmodule N` and `N`. -/
-- TODO: Show that this is perfect when `N` is a lattice and `B` is nondegenerate.
```

-- snippet 18
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.comp_apply (L142-L144)
theorem comp_apply (B : BilinForm R M') (l r : M →ₗ[R] M') (v w) : B.comp l r v w = B (l v) (r w) :=
rfl
```

-- snippet 19
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.toLinHomAux₁ (L63-L66)
def toLinHomAux₁ (A : BilinForm R M) (x : M) : M →ₗ[R] R := A x
variable (B)
```

-- snippet 20
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleToDual (L70-L81)
def dualSubmoduleToDual [IsDomain R] [IsTorsionFree R S] (N : Submodule R M) :
    B.dualSubmodule N →ₗ[R] Module.Dual R N :=
{ toFun := fun x ↦
    { toFun := B.dualSubmoduleParing x
      map_add' := fun x y ↦ FaithfulSMul.algebraMap_injective R S (by simp)
      map_smul' := fun r m ↦ FaithfulSMul.algebraMap_injective R S
        (by simp [← Algebra.smul_def]) }
    map_add' := fun x y ↦ LinearMap.ext fun z ↦ FaithfulSMul.algebraMap_injective R S
      (by simp)
    map_smul' := fun r x ↦ LinearMap.ext fun y ↦ FaithfulSMul.algebraMap_injective R S
      (by simp [← Algebra.smul_def]) }
```

-- snippet 21
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.sum_apply (L76-L83)
theorem sum_apply {α} (t : Finset α) (B : α → BilinForm R M) (v w : M) :
    (∑ i ∈ t, B i) v w = ∑ i ∈ t, B i v w := by
simp only [coe_sum, Finset.sum_apply]

variable {B}

/-- The linear map obtained from a `BilinForm` by fixing the right co-ordinate and evaluating in
the left. -/
```

-- snippet 22
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.toLin'Flip_apply (L87-L100)
theorem toLin'Flip_apply (A : BilinForm R M) (x : M) : toLinHomFlip (M := M) A x = fun y => A y x :=
rfl

end ToLin'

end BilinForm

end LinearMap

namespace LinearMap

variable {R' : Type*} [CommSemiring R'] [Algebra R' R] [Module R' M] [IsScalarTower R' R M]

/-- Apply a linear map on the output of a bilinear form. -/
```

-- snippet 23
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_dualSubmodule_flip_of_basis (L117-L125)
lemma dualSubmodule_dualSubmodule_flip_of_basis {ι : Type*} [Finite ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.dualSubmodule (B.flip.dualSubmodule (Submodule.span R (Set.range b))) =
      Submodule.span R (Set.range b) := by
classical
  letI := b.finiteDimensional_of_finite
  rw [dualSubmodule_span_of_basis _ hB.flip, dualSubmodule_span_of_basis B hB,
    dualBasis_dualBasis_flip hB]
```

-- snippet 24
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compRight_compLeft (L137-L140)
theorem compRight_compLeft (B : BilinForm R M) (l r : M →ₗ[R] M) :
    (B.compRight r).compLeft l = B.comp l r :=
rfl
```

-- snippet 25
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.sum_right (L73-L75)
theorem sum_right {α} (t : Finset α) (w : M) (g : α → M) :
    B w (∑ i ∈ t, g i) = ∑ i ∈ t, B w (g i) := map_sum _ _ _
```

-- snippet 26
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_dualSubmodule_of_basis (L135-L146)
lemma dualSubmodule_dualSubmodule_of_basis
    {ι} [Finite ι] (hB : B.Nondegenerate) (hB' : B.IsSymm) (b : Basis ι S M) :
    B.dualSubmodule (B.dualSubmodule (Submodule.span R (Set.range b))) =
      Submodule.span R (Set.range b) := by
classical
  letI := b.finiteDimensional_of_finite
  rw [dualSubmodule_span_of_basis B hB, dualSubmodule_span_of_basis B hB,
    dualBasis_dualBasis hB hB']

end BilinForm

end LinearMap
```

-- snippet 27
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.sum_left (L67-L72)
theorem sum_left {α} (t : Finset α) (g : α → M) (w : M) :
    B (∑ i ∈ t, g i) w = ∑ i ∈ t, B (g i) w :=
B.map_sum₂ t g w

variable (w : M)
```

-- snippet 28
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.le_flip_dualSubmodule (L49-L57)
lemma le_flip_dualSubmodule {N₁ N₂ : Submodule R M} :
    N₁ ≤ B.flip.dualSubmodule N₂ ↔ N₂ ≤ B.dualSubmodule N₁ := by
change (∀ (x : M), x ∈ N₁ → _) ↔ ∀ (x : M), x ∈ N₂ → _
  simp only [mem_dualSubmodule, Submodule.mem_one, flip_apply]
  exact forall₂_comm

/-- The natural paring of `B.dualSubmodule N` and `N`.
This is bundled as a bilinear map in `BilinForm.dualSubmoduleToDual`. -/
noncomputable
```

-- snippet 29
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.mem_dualSubmodule (L46-L48)
lemma mem_dualSubmodule {N : Submodule R M} {x} :
    x ∈ B.dualSubmodule N ↔ ∀ y ∈ N, B x y ∈ (1 : Submodule R S) := Iff.rfl
```

-- snippet 30
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compLeft_compRight (L132-L135)
theorem compLeft_compRight (B : BilinForm R M) (l r : M →ₗ[R] M) :
    (B.compLeft l).compRight r = B.comp l r :=
rfl
```

-- snippet 31
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compBilinForm (L102-L115)
def compBilinForm (f : R →ₗ[R'] R') (B : BilinForm R M) : BilinForm R' M :=
compr₂ (restrictScalars₁₂ R' R' B) f

end LinearMap

namespace LinearMap

namespace BilinForm

section Comp

variable {M' : Type w} [AddCommMonoid M'] [Module R M']

/-- Apply a linear map on the left and right argument of a bilinear form. -/
```

-- snippet 32
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_span_of_basis (L92-L116)
lemma dualSubmodule_span_of_basis {ι} [Finite ι] [DecidableEq ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.dualSubmodule (Submodule.span R (Set.range b)) =
      Submodule.span R (Set.range <| B.dualBasis hB b) := by
cases nonempty_fintype ι
  apply le_antisymm
  · intro x hx
    rw [← (B.dualBasis hB b).sum_repr x]
    apply sum_mem
    rintro i -
    obtain ⟨r, hr⟩ := Submodule.mem_one.mp <| hx (b i) (Submodule.subset_span ⟨_, rfl⟩)
    simp only [dualBasis_repr_apply, ← hr, algebraMap_smul]
    apply Submodule.smul_mem
    exact Submodule.subset_span ⟨_, rfl⟩
  · rw [Submodule.span_le]
    rintro _ ⟨i, rfl⟩ y hy
    obtain ⟨f, rfl⟩ := (Submodule.mem_span_range_iff_exists_fun _).mp hy
    simp only [map_sum]
    apply sum_mem
    rintro j -
    rw [← IsScalarTower.algebraMap_smul S (f j), map_smul]
    simp_rw [apply_dualBasis_left]
    rw [smul_eq_mul, mul_ite, mul_one, mul_zero, ← (algebraMap R S).map_zero, ← apply_ite]
    exact Submodule.mem_one.mpr ⟨_, rfl⟩
```

-- snippet 33
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.toLinHomFlip (L84-L86)
def toLinHomFlip : BilinForm R M →ₗ[R] M →ₗ[R] M →ₗ[R] R :=
flipHom.toLinearMap
```

-- snippet 34
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compLeft (L119-L122)
def compLeft (B : BilinForm R M) (f : M →ₗ[R] M) : BilinForm R M :=
B.comp f LinearMap.id

/-- Apply a linear map to the right argument of a bilinear form. -/
```

-- snippet 35
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule (L37-L45)
def dualSubmodule (N : Submodule R M) : Submodule R M where
  carrier := { x | ∀ y ∈ N, B x y ∈ (1 : Submodule R S) }
add_mem' {a b} ha hb y hy := by simpa using add_mem (ha y hy) (hb y hy)
  zero_mem' y _ := by rw [B.zero_left]; exact zero_mem _
  smul_mem' r a ha y hy := by
    convert (1 : Submodule R S).smul_mem r (ha y hy)
    rw [← IsScalarTower.algebraMap_smul S r a]
    simp only [algebraMap_smul, map_smul_of_tower, LinearMap.smul_apply]
```

-- snippet 36
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_flip_dualSubmodule_of_basis (L126-L134)
lemma dualSubmodule_flip_dualSubmodule_of_basis {ι : Type*} [Finite ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.flip.dualSubmodule (B.dualSubmodule (Submodule.span R (Set.range b))) =
      Submodule.span R (Set.range b) := by
classical
  letI := b.finiteDimensional_of_finite
  rw [dualSubmodule_span_of_basis B hB, dualSubmodule_span_of_basis _ hB.flip,
    dualBasis_flip_dualBasis hB]
```

-- snippet 37
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.comp_comp (L126-L130)
theorem comp_comp {M'' : Type*} [AddCommMonoid M''] [Module R M''] (B : BilinForm R M'')
    (l r : M →ₗ[R] M') (l' r' : M' →ₗ[R] M'') :
    (B.comp l' r').comp l r = B.comp (l'.comp l) (r'.comp r) :=
rfl
```

-- snippet 38
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleToDual_injective (L82-L91)
lemma dualSubmoduleToDual_injective [IsDomain R] (hB : B.Nondegenerate) [IsTorsionFree R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
intro x y e
  ext
  apply LinearMap.ker_eq_bot.mp hB.ker_eq_bot
  apply LinearMap.ext_on hN
  intro z hz
  simpa using congr_arg (algebraMap R S) (LinearMap.congr_fun e ⟨z, hz⟩)
```

-- snippet 39
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.comp (L116-L118)
def comp (B : BilinForm R M') (l r : M →ₗ[R] M') : BilinForm R M := B.compl₁₂ l r
/-- Apply a linear map to the left argument of a bilinear form. -/
```

-- snippet 40
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compRight (L123-L125)
def compRight (B : BilinForm R M) (f : M →ₗ[R] M) : BilinForm R M :=
B.comp LinearMap.id f
```

<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.LinearAlgebra.BilinearForm.Basic).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
def coeFnAddMonoidHom : BilinForm R M →+ M → M → R where
  toFun
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_left (L65-L66)
theorem add_left (x y z : M) : B (x + y) z = B x z + B y z := map_add₂ _ _ _ _
```

-- snippet 2
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left (L67-L68)
theorem smul_left (a : R) (x y : M) : B (a • x) y = a * B x y := map_smul₂ _ _ _ _
```

-- snippet 3
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.add_right (L69-L70)
theorem add_right (x y z : M) : B x (y + z) = B x y + B x z := map_add _ _ _
```

-- snippet 4
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right (L71-L72)
theorem smul_right (a : R) (x y : M) : B x (a • y) = a * B x y := map_smul _ _ _
```

-- snippet 5
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_left (L73-L74)
theorem zero_left (x : M) : B 0 x = 0 := map_zero₂ _ _
```

-- snippet 6
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.zero_right (L75-L76)
theorem zero_right (x : M) : B x 0 = 0 := map_zero _
```

-- snippet 7
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_left (L77-L78)
theorem neg_left (x y : M₁) : B₁ (-x) y = -B₁ x y := map_neg₂ _ _ _
```

-- snippet 8
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.neg_right (L79-L80)
theorem neg_right (x y : M₁) : B₁ x (-y) = -B₁ x y := map_neg _ _
```

-- snippet 9
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_left (L81-L82)
theorem sub_left (x y z : M₁) : B₁ (x - y) z = B₁ x z - B₁ y z := map_sub₂ _ _ _ _
```

-- snippet 10
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.sub_right (L83-L84)
theorem sub_right (x y z : M₁) : B₁ x (y - z) = B₁ x y - B₁ x z := map_sub _ _ _
```

-- snippet 11
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_left_of_tower (L85-L87)
lemma smul_left_of_tower (r : S) (x y : M) : B (r • x) y = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_left, Algebra.smul_def]
```

-- snippet 12
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.smul_right_of_tower (L88-L93)
lemma smul_right_of_tower (r : S) (x y : M) : B x (r • y) = r • B x y := by
rw [← IsScalarTower.algebraMap_smul R r, smul_right, Algebra.smul_def]

variable {D : BilinForm R M} {D₁ : BilinForm R₁ M₁}

-- TODO: instantiate `FunLike`
```

-- snippet 13
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.coe_injective (L94-L98)
theorem coe_injective : Function.Injective ((fun B x y => B x y) : BilinForm R M → M → M → R) :=
fun B D h => by
    ext x y
    apply congrFun₂ h
```

-- snippet 14
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.ext (L100-L101)
theorem ext (H : ∀ x y : M, B x y = D x y) : B = D := ext₂ H
```

-- snippet 15
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Basic.congr_fun (L102-L103)
theorem congr_fun (h : B = D) (x y : M) : B x y = D x y := congr_fun₂ h _ _
```

-- snippet 16
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleParing (L58-L60)
def dualSubmoduleParing {N : Submodule R M} (x : B.dualSubmodule N) (y : N) : R :=
(Submodule.mem_one.mp <| x.prop y y.prop).choose
```

-- snippet 17
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleParing_spec (L62-L67)
lemma dualSubmoduleParing_spec {N : Submodule R M} (x : B.dualSubmodule N) (y : N) :
    algebraMap R S (B.dualSubmoduleParing x y) = B x y :=
(Submodule.mem_one.mp <| x.prop y y.prop).choose_spec

/-- The natural paring of `B.dualSubmodule N` and `N`. -/
-- TODO: Show that this is perfect when `N` is a lattice and `B` is nondegenerate.
```

-- snippet 18
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.comp_apply (L142-L144)
theorem comp_apply (B : BilinForm R M') (l r : M →ₗ[R] M') (v w) : B.comp l r v w = B (l v) (r w) :=
rfl
```

-- snippet 19
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.toLinHomAux₁ (L63-L66)
def toLinHomAux₁ (A : BilinForm R M) (x : M) : M →ₗ[R] R := A x
variable (B)
```

-- snippet 20
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleToDual (L70-L81)
def dualSubmoduleToDual [IsDomain R] [IsTorsionFree R S] (N : Submodule R M) :
    B.dualSubmodule N →ₗ[R] Module.Dual R N :=
{ toFun := fun x ↦
    { toFun := B.dualSubmoduleParing x
      map_add' := fun x y ↦ FaithfulSMul.algebraMap_injective R S (by simp)
      map_smul' := fun r m ↦ FaithfulSMul.algebraMap_injective R S
        (by simp [← Algebra.smul_def]) }
    map_add' := fun x y ↦ LinearMap.ext fun z ↦ FaithfulSMul.algebraMap_injective R S
      (by simp)
    map_smul' := fun r x ↦ LinearMap.ext fun y ↦ FaithfulSMul.algebraMap_injective R S
      (by simp [← Algebra.smul_def]) }
```

-- snippet 21
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.sum_apply (L76-L83)
theorem sum_apply {α} (t : Finset α) (B : α → BilinForm R M) (v w : M) :
    (∑ i ∈ t, B i) v w = ∑ i ∈ t, B i v w := by
simp only [coe_sum, Finset.sum_apply]

variable {B}

/-- The linear map obtained from a `BilinForm` by fixing the right co-ordinate and evaluating in
the left. -/
```

-- snippet 22
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.toLin'Flip_apply (L87-L100)
theorem toLin'Flip_apply (A : BilinForm R M) (x : M) : toLinHomFlip (M := M) A x = fun y => A y x :=
rfl

end ToLin'

end BilinForm

end LinearMap

namespace LinearMap

variable {R' : Type*} [CommSemiring R'] [Algebra R' R] [Module R' M] [IsScalarTower R' R M]

/-- Apply a linear map on the output of a bilinear form. -/
```

-- snippet 23
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_dualSubmodule_flip_of_basis (L117-L125)
lemma dualSubmodule_dualSubmodule_flip_of_basis {ι : Type*} [Finite ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.dualSubmodule (B.flip.dualSubmodule (Submodule.span R (Set.range b))) =
      Submodule.span R (Set.range b) := by
classical
  letI := b.finiteDimensional_of_finite
  rw [dualSubmodule_span_of_basis _ hB.flip, dualSubmodule_span_of_basis B hB,
    dualBasis_dualBasis_flip hB]
```

-- snippet 24
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compRight_compLeft (L137-L140)
theorem compRight_compLeft (B : BilinForm R M) (l r : M →ₗ[R] M) :
    (B.compRight r).compLeft l = B.comp l r :=
rfl
```

-- snippet 25
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.sum_right (L73-L75)
theorem sum_right {α} (t : Finset α) (w : M) (g : α → M) :
    B w (∑ i ∈ t, g i) = ∑ i ∈ t, B w (g i) := map_sum _ _ _
```

-- snippet 26
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_dualSubmodule_of_basis (L135-L146)
lemma dualSubmodule_dualSubmodule_of_basis
    {ι} [Finite ι] (hB : B.Nondegenerate) (hB' : B.IsSymm) (b : Basis ι S M) :
    B.dualSubmodule (B.dualSubmodule (Submodule.span R (Set.range b))) =
      Submodule.span R (Set.range b) := by
classical
  letI := b.finiteDimensional_of_finite
  rw [dualSubmodule_span_of_basis B hB, dualSubmodule_span_of_basis B hB,
    dualBasis_dualBasis hB hB']

end BilinForm

end LinearMap
```

-- snippet 27
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.sum_left (L67-L72)
theorem sum_left {α} (t : Finset α) (g : α → M) (w : M) :
    B (∑ i ∈ t, g i) w = ∑ i ∈ t, B (g i) w :=
B.map_sum₂ t g w

variable (w : M)
```

-- snippet 28
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.le_flip_dualSubmodule (L49-L57)
lemma le_flip_dualSubmodule {N₁ N₂ : Submodule R M} :
    N₁ ≤ B.flip.dualSubmodule N₂ ↔ N₂ ≤ B.dualSubmodule N₁ := by
change (∀ (x : M), x ∈ N₁ → _) ↔ ∀ (x : M), x ∈ N₂ → _
  simp only [mem_dualSubmodule, Submodule.mem_one, flip_apply]
  exact forall₂_comm

/-- The natural paring of `B.dualSubmodule N` and `N`.
This is bundled as a bilinear map in `BilinForm.dualSubmoduleToDual`. -/
noncomputable
```

-- snippet 29
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.mem_dualSubmodule (L46-L48)
lemma mem_dualSubmodule {N : Submodule R M} {x} :
    x ∈ B.dualSubmodule N ↔ ∀ y ∈ N, B x y ∈ (1 : Submodule R S) := Iff.rfl
```

-- snippet 30
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compLeft_compRight (L132-L135)
theorem compLeft_compRight (B : BilinForm R M) (l r : M →ₗ[R] M) :
    (B.compLeft l).compRight r = B.comp l r :=
rfl
```

-- snippet 31
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compBilinForm (L102-L115)
def compBilinForm (f : R →ₗ[R'] R') (B : BilinForm R M) : BilinForm R' M :=
compr₂ (restrictScalars₁₂ R' R' B) f

end LinearMap

namespace LinearMap

namespace BilinForm

section Comp

variable {M' : Type w} [AddCommMonoid M'] [Module R M']

/-- Apply a linear map on the left and right argument of a bilinear form. -/
```

-- snippet 32
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_span_of_basis (L92-L116)
lemma dualSubmodule_span_of_basis {ι} [Finite ι] [DecidableEq ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.dualSubmodule (Submodule.span R (Set.range b)) =
      Submodule.span R (Set.range <| B.dualBasis hB b) := by
cases nonempty_fintype ι
  apply le_antisymm
  · intro x hx
    rw [← (B.dualBasis hB b).sum_repr x]
    apply sum_mem
    rintro i -
    obtain ⟨r, hr⟩ := Submodule.mem_one.mp <| hx (b i) (Submodule.subset_span ⟨_, rfl⟩)
    simp only [dualBasis_repr_apply, ← hr, algebraMap_smul]
    apply Submodule.smul_mem
    exact Submodule.subset_span ⟨_, rfl⟩
  · rw [Submodule.span_le]
    rintro _ ⟨i, rfl⟩ y hy
    obtain ⟨f, rfl⟩ := (Submodule.mem_span_range_iff_exists_fun _).mp hy
    simp only [map_sum]
    apply sum_mem
    rintro j -
    rw [← IsScalarTower.algebraMap_smul S (f j), map_smul]
    simp_rw [apply_dualBasis_left]
    rw [smul_eq_mul, mul_ite, mul_one, mul_zero, ← (algebraMap R S).map_zero, ← apply_ite]
    exact Submodule.mem_one.mpr ⟨_, rfl⟩
```

-- snippet 33
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.toLinHomFlip (L84-L86)
def toLinHomFlip : BilinForm R M →ₗ[R] M →ₗ[R] M →ₗ[R] R :=
flipHom.toLinearMap
```

-- snippet 34
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compLeft (L119-L122)
def compLeft (B : BilinForm R M) (f : M →ₗ[R] M) : BilinForm R M :=
B.comp f LinearMap.id

/-- Apply a linear map to the right argument of a bilinear form. -/
```

-- snippet 35
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule (L37-L45)
def dualSubmodule (N : Submodule R M) : Submodule R M where
  carrier := { x | ∀ y ∈ N, B x y ∈ (1 : Submodule R S) }
add_mem' {a b} ha hb y hy := by simpa using add_mem (ha y hy) (hb y hy)
  zero_mem' y _ := by rw [B.zero_left]; exact zero_mem _
  smul_mem' r a ha y hy := by
    convert (1 : Submodule R S).smul_mem r (ha y hy)
    rw [← IsScalarTower.algebraMap_smul S r a]
    simp only [algebraMap_smul, map_smul_of_tower, LinearMap.smul_apply]
```

-- snippet 36
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmodule_flip_dualSubmodule_of_basis (L126-L134)
lemma dualSubmodule_flip_dualSubmodule_of_basis {ι : Type*} [Finite ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.flip.dualSubmodule (B.dualSubmodule (Submodule.span R (Set.range b))) =
      Submodule.span R (Set.range b) := by
classical
  letI := b.finiteDimensional_of_finite
  rw [dualSubmodule_span_of_basis B hB, dualSubmodule_span_of_basis _ hB.flip,
    dualBasis_flip_dualBasis hB]
```

-- snippet 37
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.comp_comp (L126-L130)
theorem comp_comp {M'' : Type*} [AddCommMonoid M''] [Module R M''] (B : BilinForm R M'')
    (l r : M →ₗ[R] M') (l' r' : M' →ₗ[R] M'') :
    (B.comp l' r').comp l r = B.comp (l'.comp l) (r'.comp r) :=
rfl
```

-- snippet 38
```lean
-- Mathlib.LinearAlgebra.BilinearForm.DualLattice.dualSubmoduleToDual_injective (L82-L91)
lemma dualSubmoduleToDual_injective [IsDomain R] (hB : B.Nondegenerate) [IsTorsionFree R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
intro x y e
  ext
  apply LinearMap.ker_eq_bot.mp hB.ker_eq_bot
  apply LinearMap.ext_on hN
  intro z hz
  simpa using congr_arg (algebraMap R S) (LinearMap.congr_fun e ⟨z, hz⟩)
```

-- snippet 39
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.comp (L116-L118)
def comp (B : BilinForm R M') (l r : M →ₗ[R] M') : BilinForm R M := B.compl₁₂ l r
/-- Apply a linear map to the left argument of a bilinear form. -/
```

-- snippet 40
```lean
-- Mathlib.LinearAlgebra.BilinearForm.Hom.compRight (L123-L125)
def compRight (B : BilinForm R M) (f : M →ₗ[R] M) : BilinForm R M :=
B.comp LinearMap.id f
```
[/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.Order.Hom.MonoidWithZero).

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

```lean
def comp (f : β →*₀o γ) (g : α →*₀o β) : α →*₀o γ
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.OrderMonoidWithZeroHomClass (L69-L72)
def OrderMonoidWithZeroHomClass.toOrderMonoidWithZeroHom [OrderHomClass F α β]
    [MonoidWithZeroHomClass F α β] (f : F) : α →*₀o β :=
{ (f : α →*₀ β) with monotone' := OrderHomClass.monotone f }
```

-- snippet 2
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.ext (L108-L110)
theorem ext (h : ∀ a, f a = g a) : f = g :=
DFunLike.ext f g h
```

-- snippet 3
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toFun_eq_coe (L111-L113)
theorem toFun_eq_coe (f : α →*₀o β) : f.toFun = (f : α → β) :=
rfl
```

-- snippet 4
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_mk (L115-L117)
theorem coe_mk (f : α →*₀ β) (h) : (OrderMonoidWithZeroHom.mk f h : α → β) = f :=
rfl
```

-- snippet 5
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.mk_coe (L119-L121)
theorem mk_coe (f : α →*₀o β) (h) : OrderMonoidWithZeroHom.mk (f : α →*₀ β) h = f := rfl
/-- Reinterpret an ordered monoid with zero homomorphism as an order monoid homomorphism. -/
```

-- snippet 6
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toOrderMonoidHom (L122-L124)
def toOrderMonoidHom (f : α →*₀o β) : α →*o β :=
{ f with }
```

-- snippet 7
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_monoidWithZeroHom (L126-L128)
theorem coe_monoidWithZeroHom (f : α →*₀o β) : ⇑(f : α →*₀ β) = f :=
rfl
```

-- snippet 8
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_orderMonoidHom (L130-L132)
theorem coe_orderMonoidHom (f : α →*₀o β) : ⇑(f : α →*o β) = f :=
rfl
```

-- snippet 9
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toOrderMonoidHom_injective (L133-L135)
theorem toOrderMonoidHom_injective : Injective (toOrderMonoidHom : _ → α →*o β) := fun f g h =>
ext <| by convert DFunLike.ext_iff.1 h using 0
```

-- snippet 10
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toMonoidWithZeroHom_injective (L136-L139)
theorem toMonoidWithZeroHom_injective : Injective (toMonoidWithZeroHom : _ → α →*₀ β) :=
fun f g h => ext <| by convert DFunLike.ext_iff.1 h using 0

/-- Copy of an `OrderMonoidWithZeroHom` with a new `toFun` equal to the old one. Useful to fix
```

-- snippet 11
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_copy (L145-L147)
theorem coe_copy (f : α →*₀o β) (f' : α → β) (h : f' = f) : ⇑(f.copy f' h) = f' :=
rfl
```

-- snippet 12
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.copy_eq (L148-L156)
theorem copy_eq (f : α →*₀o β) (f' : α → β) (h : f' = f) : f.copy f' h = f :=
DFunLike.ext' h

variable (α)

/-- The identity map as an ordered monoid with zero homomorphism. -/
protected def id : α →*₀o α :=
  { MonoidWithZeroHom.id α, OrderHom.id with }
```

-- snippet 13
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_id (L158-L160)
theorem coe_id : ⇑(OrderMonoidWithZeroHom.id α) = id :=
rfl
```

-- snippet 14
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_comp (L171-L173)
theorem coe_comp (f : β →*₀o γ) (g : α →*₀o β) : (f.comp g : α → γ) = f ∘ g :=
rfl
```

-- snippet 15
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.comp_apply (L175-L177)
theorem comp_apply (f : β →*₀o γ) (g : α →*₀o β) (a : α) : (f.comp g) a = f (g a) :=
rfl
```

-- snippet 16
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_comp_monoidWithZeroHom (L178-L181)
theorem coe_comp_monoidWithZeroHom (f : β →*₀o γ) (g : α →*₀o β) :
    (f.comp g : α →*₀ γ) = (f : β →*₀ γ).comp g :=
rfl
```

-- snippet 17
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_comp_orderMonoidHom (L182-L185)
theorem coe_comp_orderMonoidHom (f : β →*₀o γ) (g : α →*₀o β) :
    (f.comp g : α →*o γ) = (f : β →*o γ).comp g :=
rfl
```

-- snippet 18
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.comp_assoc (L187-L190)
theorem comp_assoc (f : γ →*₀o δ) (g : β →*₀o γ) (h : α →*₀o β) :
    (f.comp g).comp h = f.comp (g.comp h) :=
rfl
```

-- snippet 19
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.comp_id (L192-L193)
theorem comp_id (f : α →*₀o β) : f.comp (OrderMonoidWithZeroHom.id α) = f := rfl
```

-- snippet 20
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.id_comp (L195-L196)
theorem id_comp (f : α →*₀o β) : (OrderMonoidWithZeroHom.id β).comp f = f := rfl
```

-- snippet 21
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.cancel_right (L198-L201)
theorem cancel_right {g₁ g₂ : β →*₀o γ} {f : α →*₀o β} (hf : Function.Surjective f) :
    g₁.comp f = g₂.comp f ↔ g₁ = g₂ :=
⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun _ => by congr⟩
```

-- snippet 22
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.cancel_left (L203-L215)
theorem cancel_left {g : β →*₀o γ} {f₁ f₂ : α →*₀o β} (hg : Function.Injective g) :
    g.comp f₁ = g.comp f₂ ↔ f₁ = f₂ :=
⟨fun h => ext fun a => hg <| by rw [← comp_apply, h, comp_apply], congr_arg _⟩

end Preorder

section Mul

variable [LinearOrderedCommMonoidWithZero α] [LinearOrderedCommMonoidWithZero β]
  [LinearOrderedCommMonoidWithZero γ]

/-- For two ordered monoid morphisms `f` and `g`, their product is the ordered monoid morphism
sending `a` to `f a * g a`. -/
```

-- snippet 23
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_mul (L220-L222)
theorem coe_mul (f g : α →*₀o β) : ⇑(f * g) = f * g :=
rfl
```

-- snippet 24
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.mul_apply (L224-L226)
theorem mul_apply (f g : α →*₀o β) (a : α) : (f * g) a = f a * g a :=
rfl
```

-- snippet 25
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.mul_comp (L227-L229)
theorem mul_comp (g₁ g₂ : β →*₀o γ) (f : α →*₀o β) : (g₁ * g₂).comp f = g₁.comp f * g₂.comp f :=
rfl
```

-- snippet 26
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.nonnegHomClass (L65-L67)
instance nonnegHomClass : NonnegHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with apply_nonneg := fun f => f.nonneg' }
```

-- snippet 27
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.mulHomClass (L62-L64)
instance mulHomClass : MulHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_mul := fun f => f.map_mul' }
```

-- snippet 28
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.ext (L76-L79)
theorem ext ⦃f g : AbsoluteValue R S⦄ : (∀ x, f x = g x) → f = g :=
DFunLike.ext _ _

/-- See Note [custom simps projection]. -/
```

-- snippet 29
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_eq_zero (L426-L427)
lemma abv_eq_zero {x} : abv x = 0 ↔ x = 0 := abv_eq_zero'
```

-- snippet 30
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidWithZeroHom (L165-L167)
def toMonoidWithZeroHom : R →*₀ S :=
abv
```

-- snippet 31
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.subadditiveHomClass (L68-L70)
instance subadditiveHomClass : SubadditiveHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_add_le_add := fun f => f.add_le' }
```

-- snippet 32
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_pos (L451-L459)
theorem abv_pos {a : R} : 0 < abv a ↔ a ≠ 0 :=
(toAbsoluteValue abv).pos_iff

end OrderedSemiring

section LinearOrderedRing

variable {S : Type*} [Ring S] [LinearOrder S] [IsStrictOrderedRing S]
```

-- snippet 33
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_right_inj_of_ne_top (L195-L197)
lemma sub_right_inj_of_ne_top (h : a ≠ ⊤) : a - b = a - c ↔ b = c :=
(sub_right_injective_of_ne_top h).eq_iff
```

-- snippet 34
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_one' (L537-L541)
theorem abv_one' : abv 1 = 1 :=
(toAbsoluteValue abv).map_one_of_isLeftRegular <|
    (IsRegular.of_ne_zero <| (toAbsoluteValue abv).ne_zero one_ne_zero).left

/-- An absolute value as a monoid with zero homomorphism, assuming the target is a semifield. -/
```

-- snippet 35
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidHom (L177-L179)
theorem coe_toMonoidHom : ⇑abv.toMonoidHom = abv :=
rfl
```

-- snippet 36
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidWithZeroHom (L169-L172)
theorem coe_toMonoidWithZeroHom : ⇑abv.toMonoidWithZeroHom = abv :=
rfl

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*` and `1`. -/
```

-- snippet 37
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMulHom (L86-L88)
theorem coe_toMulHom : ⇑abv.toMulHom = abv :=
rfl
```

-- snippet 38
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_sub_le (L491-L493)
theorem abv_sub_le (a b c : R) : abv (a - c) ≤ abv (a - b) + abv (b - c) := by
simpa [sub_eq_add_neg, add_assoc] using abv_add abv (a - b) (b - c)
```

-- snippet 39
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.eq_on_nat_iff_eq_on_int (L256-L268)
lemma eq_on_nat_iff_eq_on_int {f g : AbsoluteValue R S} :
    (∀ n : ℕ, f n = g n) ↔ ∀ n : ℤ, f n = g n := by
refine ⟨fun h z ↦ ?_, fun a n ↦ mod_cast a n⟩
  obtain ⟨n, rfl | rfl⟩ := Int.eq_nat_or_neg z <;> simp [h n]

end OrderedCommRing

section LinearOrderedRing

variable {R S : Type*} [Semiring R] [Ring S] [LinearOrder S] [IsStrictOrderedRing S]
  (abv : AbsoluteValue R S)

/-- `AbsoluteValue.abs` is `abs` as a bundled `AbsoluteValue`. -/
```

-- snippet 40
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_right_strictMono_of_ne_top (L85-L87)
lemma add_right_strictMono_of_ne_top (h : b ≠ ⊤) : StrictMono (fun x ↦ b + x) :=
add_right_mono.strictMono_of_injective <| add_right_injective_of_ne_top _ h
```

-- snippet 41
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_sub_eq_zero_iff (L141-L154)
theorem map_sub_eq_zero_iff (a b : R) : abv (a - b) = 0 ↔ a = b :=
abv.eq_zero.trans sub_eq_zero

end Ring

section Semiring

section IsDomain

-- all of these are true for `NoZeroDivisors S`; but it doesn't work smoothly with the
-- `IsDomain`/`IsCancelMulZero` API
variable {R S : Type*} [Semiring R] [Semiring S] [PartialOrder S] (abv : AbsoluteValue R S)
variable [IsDomain S] [Nontrivial R]
```

-- snippet 42
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_nat_le_self (L186-L206)
lemma apply_nat_le_self [IsOrderedRing S] (n : ℕ) : abv n ≤ n := by
cases subsingleton_or_nontrivial R
  · simp [Subsingleton.eq_zero (n : R)]
  induction n with
  | zero => simp
  | succ n ih =>
  · grw [Nat.cast_succ, Nat.cast_succ, abv.add_le, abv.map_one, ih]

end IsDomain

end Semiring

end OrderedSemiring

section OrderedRing

section Ring

variable {R S : Type*} [Ring R] [Ring S] [PartialOrder S] [IsOrderedRing S]
  (abv : AbsoluteValue R S)
```

-- snippet 43
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_neg (L505-L507)
theorem abv_neg (a : R) : abv (-a) = abv a :=
(toAbsoluteValue abv).map_neg a
```

-- snippet 44
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_add_cancel_right_of_ne_top (L128-L130)
lemma neg_add_cancel_right_of_ne_top (hb : b ≠ ⊤) (a : α) : a + -b + b = a := by
simp [add_assoc, neg_add_cancel_of_ne_top hb]
```

-- snippet 45
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.listSum_le (L102-L106)
lemma listSum_le [AddLeftMono S] (l : List R) : abv l.sum ≤ (l.map abv).sum := by
induction l with
  | nil => simp
  | cons head tail ih => exact (abv.add_le ..).trans <| add_le_add_right ih (abv head)
```

-- snippet 46
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.not_isNontrivial_iff (L350-L356)
lemma not_isNontrivial_iff (v : AbsoluteValue R S) :
    ¬ v.IsNontrivial ↔ ∀ x ≠ 0, v x = 1 := by
simp only [IsNontrivial]
  push Not
  rfl

omit [IsOrderedRing S] in
```

-- snippet 47
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_left_injective_of_ne_top (L68-L70)
lemma add_left_injective_of_ne_top (b : α) (h : b ≠ ⊤) : Function.Injective (fun x ↦ x + b) :=
(IsAddRegular.of_ne_top h).2
```

-- snippet 48
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abvHom' (L542-L556)
def abvHom' : R →*₀ S where
  toFun := abv; map_zero' := abv_zero abv; map_one' := abv_one' abv; map_mul' := abv_mul abv
end Semiring

end IsCancelMulZero

section LinearOrderedSemifield

variable {S : Type*} [Semifield S] [LinearOrder S]

section DivisionSemiring

variable {R : Type*} [DivisionSemiring R] (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 49
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_nonneg (L412-L417)
lemma abv_nonneg (x) : 0 ≤ abv x := abv_nonneg' x
open Lean Meta Mathlib Meta Positivity Qq in
/-- The `positivity` extension which identifies expressions of the form `abv a`.
For performance reasons, we only attempt to apply this when `abv` is a variable.
If it is an explicit function, e.g. `|_|` or `‖_‖`, another extension should apply. -/
```

-- snippet 50
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial (L300-L317)
def trivial : AbsoluteValue R S where
  toFun x := if x = 0 then 0 else 1
map_mul' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp [hx, hy]
  nonneg' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  eq_zero' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  add_le' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp only [hx, ↓reduceIte, hy, one_add_one_eq_two]
    rcases eq_or_ne (x + y) 0 with hxy | hxy <;> simp [hxy, one_le_two]
```

-- snippet 51
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toAbsoluteValue (L441-L447)
def toAbsoluteValue : AbsoluteValue R S where
  toFun := abv
add_le' := abv_add'
  eq_zero' _ := abv_eq_zero'
  nonneg' := abv_nonneg'
  map_mul' := abv_mul'
```

-- snippet 52
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_left_injective_of_ne_top (L184-L186)
lemma sub_left_injective_of_ne_top (h : b ≠ ⊤) : Function.Injective fun x ↦ x - b := by
simpa [sub_eq_add_neg] using add_left_injective_of_ne_top (-b) (by simpa)
```

-- snippet 53
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_right_injective_of_ne_top (L71-L73)
lemma add_right_injective_of_ne_top (b : α) (h : b ≠ ⊤) : Function.Injective (fun x ↦ b + x) :=
(IsAddRegular.of_ne_top h).1
```

-- snippet 54
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_right_injective_of_ne_top (L187-L189)
lemma sub_right_injective_of_ne_top (h : b ≠ ⊤) : Function.Injective fun x ↦ b - x := by
simpa [sub_eq_add_neg] using (add_right_injective_of_ne_top b h).comp neg_injective
```

-- snippet 55
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_mul (L430-L432)
lemma abv_mul (x y) : abv (x * y) = abv x * abv y := abv_mul' x y
/-- A bundled absolute value is an absolute value. -/
```

-- snippet 56
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Euclidean.map_lt_map_iff (L50-L52)
theorem map_lt_map_iff {x y : R} (h : abv.IsEuclidean) : abv x < abv y ↔ x ≺ y :=
map_lt_map_iff' h
```

-- snippet 57
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abs_abv_sub_le_abv_sub (L288-L299)
theorem abs_abv_sub_le_abv_sub (a b : R) : abs (abv a - abv b) ≤ abv (a - b) :=
abs_sub_le_iff.2 ⟨abv.le_sub _ _, by rw [abv.map_sub]; apply abv.le_sub⟩

end LinearOrderedCommRing

section trivial

variable {R : Type*} [Semiring R] [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R]
variable {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S] [Nontrivial S]

/-- The *trivial* absolute value takes the value `1` on all nonzero elements. -/
protected
```

-- snippet 58
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_self_nonneg (L236-L240)
lemma sub_self_nonneg : 0 ≤ a - a := by
obtain rfl | ha := eq_or_ne a ⊤
  · simp
  · rw [sub_self_eq_zero_of_ne_top ha]
```

-- snippet 59
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.IsNontrivial (L335-L337)
def IsNontrivial (v : AbsoluteValue R S) : Prop :=
∃ x ≠ 0, v x ≠ 1
```

-- snippet 60
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_div (L560-L567)
theorem abv_div (a b : R) : abv (a / b) = abv a / abv b :=
map_div₀ (abvHom' abv) a b

end DivisionSemiring

end LinearOrderedSemifield

end IsAbsoluteValue
```

-- snippet 61
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_lt_add_iff_right_of_ne_top (L101-L109)
lemma add_lt_add_iff_right_of_ne_top (h : a ≠ ⊤) : a + b < a + c ↔ b < c :=
(add_right_strictMono_of_ne_top h).lt_iff_lt

end LinearOrderedAddCommMonoidWithTop

namespace LinearOrderedAddCommGroupWithTop

variable [LinearOrderedAddCommGroupWithTop α] {a b c : α}
```

-- snippet 62
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.not_isNontrivial_apply (L358-L368)
lemma not_isNontrivial_apply {v : AbsoluteValue R S} (hv : ¬ v.IsNontrivial) {x : R} (hx : x ≠ 0) :
    v x = 1 :=
v.not_isNontrivial_iff.mp hv _ hx

end OrderedSemiring

section LinearOrderedSemifield

variable [Field R] [Semifield S] [LinearOrder S] [IsStrictOrderedRing S] [ExistsAddOfLE S]
  {v : AbsoluteValue R S}
```

-- snippet 63
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_add (L428-L429)
lemma abv_add (x y) : abv (x + y) ≤ abv x + abv y := abv_add' x y
```

-- snippet 64
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_pos (L232-L234)
lemma neg_pos : 0 < -a ↔ a < 0 ∨ a = ⊤ := by
simpa using sub_pos (a := 0) (b := a)
```

-- snippet 65
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_le_add_iff_left_of_ne_top (L89-L91)
lemma add_le_add_iff_left_of_ne_top (h : a ≠ ⊤) : b + a ≤ c + a ↔ b ≤ c :=
(add_left_strictMono_of_ne_top h).le_iff_le
```

-- snippet 66
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.monoidWithZeroHomClass (L159-L164)
instance monoidWithZeroHomClass : MonoidWithZeroHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.mulHomClass with
    map_zero := fun f => f.map_zero
    map_one := fun f => f.map_one }

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*`, `0` and `1`. -/
```

-- snippet 67
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_sub (L508-L520)
theorem abv_sub (a b : R) : abv (a - b) = abv (b - a) :=
(toAbsoluteValue abv).map_sub a b

end OrderedCommRing

section LinearOrderedCommRing

variable {S : Type*} [CommRing S] [LinearOrder S] [IsStrictOrderedRing S]

section Ring

variable {R : Type*} [Ring R] (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 68
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_inv (L557-L559)
theorem abv_inv (a : R) : abv a⁻¹ = (abv a)⁻¹ :=
map_inv₀ (abvHom' abv) a
```

-- snippet 69
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_left_strictMono_of_ne_top (L82-L84)
lemma add_left_strictMono_of_ne_top (h : b ≠ ⊤) : StrictMono (fun x ↦ x + b) :=
add_left_mono.strictMono_of_injective <| add_left_injective_of_ne_top _ h
```

-- snippet 70
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.sub_le_add (L235-L237)
lemma sub_le_add (a b : R) : abv (a - b) ≤ abv a + abv b := by
simpa only [← sub_eq_add_neg, AbsoluteValue.map_neg] using abv.add_le a (-b)
```

-- snippet 71
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abvHom (L478-L480)
def abvHom [Nontrivial R] : R →*₀ S :=
(toAbsoluteValue abv).toMonoidWithZeroHom
```

-- snippet 72
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_lt_sub_iff_left_of_ne_top (L212-L214)
lemma sub_lt_sub_iff_left_of_ne_top (h : a ≠ ⊤) : b - a < c - a ↔ b < c :=
(sub_left_strictMono_of_ne_top h).lt_iff_lt
```

-- snippet 73
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_left_inj_of_ne_top (L75-L77)
lemma add_left_inj_of_ne_top (h : a ≠ ⊤) : b + a = c + a ↔ b = c :=
(add_left_injective_of_ne_top _ h).eq_iff
```

-- snippet 74
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_right_inj_of_ne_top (L79-L81)
lemma add_right_inj_of_ne_top (h : a ≠ ⊤) : a + b = a + c ↔ b = c :=
(add_right_injective_of_ne_top _ h).eq_iff
```

-- snippet 75
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.Simps (L80-L84)
def Simps.apply (f : AbsoluteValue R S) : R → S :=
f

initialize_simps_projections AbsoluteValue (toFun → apply)
```

-- snippet 76
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_top (L62-L64)
theorem add_top (a : α) : a + ⊤ = ⊤ :=
Trans.trans (add_comm _ _) (top_add _)
```

-- snippet 77
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_one (L474-L477)
theorem abv_one [Nontrivial R] : abv 1 = 1 :=
(toAbsoluteValue abv).map_one

/-- `abv` as a `MonoidWithZeroHom`. -/
```

-- snippet 78
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_le_sub_iff_left_of_ne_top (L208-L210)
lemma sub_le_sub_iff_left_of_ne_top (h : a ≠ ⊤) : b - a ≤ c - a ↔ b ≤ c :=
(sub_left_strictMono_of_ne_top h).le_iff_le
```

-- snippet 79
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.top_add (L58-L60)
theorem top_add (a : α) : ⊤ + a = ⊤ :=
LinearOrderedAddCommMonoidWithTop.top_add' a
```

-- snippet 80
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_pos (L226-L230)
lemma sub_pos : 0 < a - b ↔ b < a ∨ b = ⊤ := by
obtain rfl | hb := eq_or_ne b ⊤
  · simp
  · simp [← sub_self_eq_zero_of_ne_top hb, hb]
```

-- snippet 81
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_left_strictMono_of_ne_top (L204-L206)
lemma sub_left_strictMono_of_ne_top (h : b ≠ ⊤) : StrictMono fun x ↦ x - b := by
simpa [sub_eq_add_neg] using add_left_strictMono_of_ne_top (b := -b) (by simpa)
```

-- snippet 82
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_lt_add_iff_left_of_ne_top (L97-L99)
lemma add_lt_add_iff_left_of_ne_top (h : a ≠ ⊤) : b + a < c + a ↔ b < c :=
(add_left_strictMono_of_ne_top h).lt_iff_lt
```

-- snippet 83
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_pow (L481-L490)
theorem abv_pow [Nontrivial R] (abv : R → S) [IsAbsoluteValue abv] (a : R) (n : ℕ) :
    abv (a ^ n) = abv a ^ n :=
(toAbsoluteValue abv).map_pow a n

end Semiring

section Ring

variable {R : Type*} [Ring R] (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 84
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_neg_cancel_left_of_ne_top (L119-L121)
lemma add_neg_cancel_left_of_ne_top (ha : a ≠ ⊤) (b : α) : a + (-a + b) = b := by
simp [← add_assoc, add_neg_cancel_of_ne_top ha]
```

-- snippet 85
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_natAbs_eq (L250-L255)
lemma apply_natAbs_eq (x : ℤ) : abv (natAbs x) = abv x := by
obtain ⟨_, rfl | rfl⟩ := Int.eq_nat_or_neg x <;> simp

open Int in
/-- Values of an absolute value coincide on the image of `ℕ` in `R`
if and only if they coincide on the image of `ℤ` in `R`. -/
```

-- snippet 86
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidHom (L173-L175)
def toMonoidHom : R →* S :=
abv
```

-- snippet 87
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.funLike (L55-L58)
instance funLike : FunLike (AbsoluteValue R S) R S where
  coe f := f.toFun
coe_injective' f g h := by obtain ⟨⟨_, _⟩, _⟩ := f; obtain ⟨⟨_, _⟩, _⟩ := g; congr
```

-- snippet 88
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_ne_top (L149-L150)
lemma add_ne_top : a + b ≠ ⊤ ↔ a ≠ ⊤ ∧ b ≠ ⊤ := by simp [← isAddUnit_iff]
```

-- snippet 89
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.addGroupSeminormClass (L238-L242)
instance addGroupSeminormClass : AddGroupSeminormClass (AbsoluteValue R S) R S where
  toSubadditiveHomClass := AbsoluteValue.subadditiveHomClass
map_zero := AbsoluteValue.map_zero
  map_neg_eq_map f a := AbsoluteValue.map_neg f a
```

-- snippet 90
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_one_of_isLeftRegular (L124-L126)
theorem map_one_of_isLeftRegular (h : IsLeftRegular (abv 1)) : abv 1 = 1 :=
h <| by simp [← abv.map_mul]
```

-- snippet 91
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_add_cancel_of_ne_top (L116-L118)
lemma neg_add_cancel_of_ne_top (ha : a ≠ ⊤) : -a + a = 0 := by
simp [add_comm, add_neg_cancel_of_ne_top ha]
```

-- snippet 92
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abs_isAbsoluteValue (L460-L473)
instance abs_isAbsoluteValue : IsAbsoluteValue (abs : S → S) :=
AbsoluteValue.abs.isAbsoluteValue

end LinearOrderedRing

section OrderedRing

variable {S : Type*} [Ring S] [PartialOrder S]

section Semiring

variable {R : Type*} [Semiring R] (abv : R → S) [IsAbsoluteValue abv]
variable [IsDomain S]
```

-- snippet 93
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_self_eq_zero_iff_ne_top (L221-L225)
lemma sub_self_eq_zero_iff_ne_top : a - a = 0 ↔ a ≠ ⊤ := by
rw [sub_eq_add_neg, add_neg_cancel_iff_ne_top]

alias ⟨_, sub_self_eq_zero_of_ne_top⟩ := sub_self_eq_zero_iff_ne_top
```

-- snippet 94
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial_apply (L319-L334)
lemma trivial_apply {x : R} (hx : x ≠ 0) : AbsoluteValue.trivial (S := S) x = 1 :=
if_neg hx

end trivial

section nontrivial

section OrderedSemiring

variable {R : Type*} [Semiring R] {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S]

/-- An absolute value on a semiring `R` without zero divisors is *nontrivial* if it takes
a value `≠ 1` on a nonzero element.

This has the advantage over `v ≠ .trivial` that it does not require decidability
of `· = 0` in `R`. -/
```

-- snippet 95
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Euclidean.sub_mod_lt (L55-L74)
theorem sub_mod_lt (h : abv.IsEuclidean) (a : R) {b : R} (hb : b ≠ 0) : abv (a % b) < abv b :=
h.map_lt_map_iff.mpr (EuclideanDomain.mod_lt a hb)

end IsEuclidean

end OrderedSemiring

section Int

open Int

-- TODO: generalize to `LinearOrderedEuclideanDomain`s if we ever get a definition of those
/-- `abs : ℤ → ℤ` is a Euclidean absolute value -/
protected theorem abs_isEuclidean : IsEuclidean (AbsoluteValue.abs : AbsoluteValue ℤ ℤ) :=
  { map_lt_map_iff' := fun {x y} =>
       show abs x < abs y ↔ natAbs x < natAbs y by rw [abs_eq_natAbs, abs_eq_natAbs, ofNat_lt] }

end Int

end AbsoluteValue
```

-- snippet 96
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_le_add_iff_right_of_ne_top (L93-L95)
lemma add_le_add_iff_right_of_ne_top (h : a ≠ ⊤) : a + b ≤ a + c ↔ b ≤ c :=
(add_right_strictMono_of_ne_top h).le_iff_le
```

-- snippet 97
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_zero (L448-L450)
theorem abv_zero : abv 0 = 0 :=
(toAbsoluteValue abv).map_zero
```

-- snippet 98
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_neg_cancel_iff_ne_top (L216-L219)
lemma add_neg_cancel_iff_ne_top : a + -a = 0 ↔ a ≠ ⊤ where
  mp := by contrapose; simp +contextual
mpr h := add_neg_cancel_of_ne_top h
```

-- snippet 99
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_mk (L72-L74)
theorem coe_mk (f : R →ₙ* S) {h₁ h₂ h₃} : (AbsoluteValue.mk f h₁ h₂ h₃ : R → S) = f :=
rfl
```

-- snippet 100
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_add_cancel_left_of_ne_top (L122-L124)
lemma neg_add_cancel_left_of_ne_top (ha : a ≠ ⊤) (b : α) : -a + (a + b) = b := by
simp [← add_assoc, neg_add_cancel_of_ne_top ha]
```

-- snippet 101
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.isNontrivial_iff_ne_trivial (L338-L349)
lemma isNontrivial_iff_ne_trivial [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R]
    [Nontrivial S] (v : AbsoluteValue R S) :
    v.IsNontrivial ↔ v ≠ .trivial := by
refine ⟨fun ⟨x, hx₀, hx₁⟩ h ↦ hx₁ <| h.symm ▸ trivial_apply hx₀, fun H ↦ ?_⟩
  simp only [IsNontrivial]
  contrapose! H
  ext1 x
  rcases eq_or_ne x 0 with rfl | hx
  · simp
  · simp [H, hx]

omit [IsOrderedRing S] in
```

-- snippet 102
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.zeroHomClass (L59-L61)
instance zeroHomClass : ZeroHomClass (AbsoluteValue R S) R S where
  map_zero f := (f.eq_zero' _).2 rfl
```

-- snippet 103
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_neg_cancel_right_of_ne_top (L125-L127)
lemma add_neg_cancel_right_of_ne_top (hb : b ≠ ⊤) (a : α) : a + b + -b = a := by
simp [add_assoc, add_neg_cancel_of_ne_top hb]
```

-- snippet 104
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.sub_abv_le_abv_sub (L494-L504)
theorem sub_abv_le_abv_sub [IsOrderedRing S] (a b : R) : abv a - abv b ≤ abv (a - b) :=
(toAbsoluteValue abv).le_sub a b

end Ring

end OrderedRing

section OrderedCommRing
variable [CommRing S] [PartialOrder S] [IsOrderedRing S] [NoZeroDivisors S] [Ring R]
  (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 105
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_left_inj_of_ne_top (L191-L193)
lemma sub_left_inj_of_ne_top (h : a ≠ ⊤) : b - a = c - a ↔ b = c :=
(sub_left_injective_of_ne_top h).eq_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.Algebra.Order.Hom.MonoidWithZero).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
def comp (f : β →*₀o γ) (g : α →*₀o β) : α →*₀o γ
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.OrderMonoidWithZeroHomClass (L69-L72)
def OrderMonoidWithZeroHomClass.toOrderMonoidWithZeroHom [OrderHomClass F α β]
    [MonoidWithZeroHomClass F α β] (f : F) : α →*₀o β :=
{ (f : α →*₀ β) with monotone' := OrderHomClass.monotone f }
```

-- snippet 2
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.ext (L108-L110)
theorem ext (h : ∀ a, f a = g a) : f = g :=
DFunLike.ext f g h
```

-- snippet 3
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toFun_eq_coe (L111-L113)
theorem toFun_eq_coe (f : α →*₀o β) : f.toFun = (f : α → β) :=
rfl
```

-- snippet 4
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_mk (L115-L117)
theorem coe_mk (f : α →*₀ β) (h) : (OrderMonoidWithZeroHom.mk f h : α → β) = f :=
rfl
```

-- snippet 5
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.mk_coe (L119-L121)
theorem mk_coe (f : α →*₀o β) (h) : OrderMonoidWithZeroHom.mk (f : α →*₀ β) h = f := rfl
/-- Reinterpret an ordered monoid with zero homomorphism as an order monoid homomorphism. -/
```

-- snippet 6
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toOrderMonoidHom (L122-L124)
def toOrderMonoidHom (f : α →*₀o β) : α →*o β :=
{ f with }
```

-- snippet 7
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_monoidWithZeroHom (L126-L128)
theorem coe_monoidWithZeroHom (f : α →*₀o β) : ⇑(f : α →*₀ β) = f :=
rfl
```

-- snippet 8
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_orderMonoidHom (L130-L132)
theorem coe_orderMonoidHom (f : α →*₀o β) : ⇑(f : α →*o β) = f :=
rfl
```

-- snippet 9
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toOrderMonoidHom_injective (L133-L135)
theorem toOrderMonoidHom_injective : Injective (toOrderMonoidHom : _ → α →*o β) := fun f g h =>
ext <| by convert DFunLike.ext_iff.1 h using 0
```

-- snippet 10
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.toMonoidWithZeroHom_injective (L136-L139)
theorem toMonoidWithZeroHom_injective : Injective (toMonoidWithZeroHom : _ → α →*₀ β) :=
fun f g h => ext <| by convert DFunLike.ext_iff.1 h using 0

/-- Copy of an `OrderMonoidWithZeroHom` with a new `toFun` equal to the old one. Useful to fix
```

-- snippet 11
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_copy (L145-L147)
theorem coe_copy (f : α →*₀o β) (f' : α → β) (h : f' = f) : ⇑(f.copy f' h) = f' :=
rfl
```

-- snippet 12
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.copy_eq (L148-L156)
theorem copy_eq (f : α →*₀o β) (f' : α → β) (h : f' = f) : f.copy f' h = f :=
DFunLike.ext' h

variable (α)

/-- The identity map as an ordered monoid with zero homomorphism. -/
protected def id : α →*₀o α :=
  { MonoidWithZeroHom.id α, OrderHom.id with }
```

-- snippet 13
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_id (L158-L160)
theorem coe_id : ⇑(OrderMonoidWithZeroHom.id α) = id :=
rfl
```

-- snippet 14
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_comp (L171-L173)
theorem coe_comp (f : β →*₀o γ) (g : α →*₀o β) : (f.comp g : α → γ) = f ∘ g :=
rfl
```

-- snippet 15
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.comp_apply (L175-L177)
theorem comp_apply (f : β →*₀o γ) (g : α →*₀o β) (a : α) : (f.comp g) a = f (g a) :=
rfl
```

-- snippet 16
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_comp_monoidWithZeroHom (L178-L181)
theorem coe_comp_monoidWithZeroHom (f : β →*₀o γ) (g : α →*₀o β) :
    (f.comp g : α →*₀ γ) = (f : β →*₀ γ).comp g :=
rfl
```

-- snippet 17
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_comp_orderMonoidHom (L182-L185)
theorem coe_comp_orderMonoidHom (f : β →*₀o γ) (g : α →*₀o β) :
    (f.comp g : α →*o γ) = (f : β →*o γ).comp g :=
rfl
```

-- snippet 18
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.comp_assoc (L187-L190)
theorem comp_assoc (f : γ →*₀o δ) (g : β →*₀o γ) (h : α →*₀o β) :
    (f.comp g).comp h = f.comp (g.comp h) :=
rfl
```

-- snippet 19
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.comp_id (L192-L193)
theorem comp_id (f : α →*₀o β) : f.comp (OrderMonoidWithZeroHom.id α) = f := rfl
```

-- snippet 20
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.id_comp (L195-L196)
theorem id_comp (f : α →*₀o β) : (OrderMonoidWithZeroHom.id β).comp f = f := rfl
```

-- snippet 21
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.cancel_right (L198-L201)
theorem cancel_right {g₁ g₂ : β →*₀o γ} {f : α →*₀o β} (hf : Function.Surjective f) :
    g₁.comp f = g₂.comp f ↔ g₁ = g₂ :=
⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun _ => by congr⟩
```

-- snippet 22
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.cancel_left (L203-L215)
theorem cancel_left {g : β →*₀o γ} {f₁ f₂ : α →*₀o β} (hg : Function.Injective g) :
    g.comp f₁ = g.comp f₂ ↔ f₁ = f₂ :=
⟨fun h => ext fun a => hg <| by rw [← comp_apply, h, comp_apply], congr_arg _⟩

end Preorder

section Mul

variable [LinearOrderedCommMonoidWithZero α] [LinearOrderedCommMonoidWithZero β]
  [LinearOrderedCommMonoidWithZero γ]

/-- For two ordered monoid morphisms `f` and `g`, their product is the ordered monoid morphism
sending `a` to `f a * g a`. -/
```

-- snippet 23
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.coe_mul (L220-L222)
theorem coe_mul (f g : α →*₀o β) : ⇑(f * g) = f * g :=
rfl
```

-- snippet 24
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.mul_apply (L224-L226)
theorem mul_apply (f g : α →*₀o β) (a : α) : (f * g) a = f a * g a :=
rfl
```

-- snippet 25
```lean
-- Mathlib.Algebra.Order.Hom.MonoidWithZero.mul_comp (L227-L229)
theorem mul_comp (g₁ g₂ : β →*₀o γ) (f : α →*₀o β) : (g₁ * g₂).comp f = g₁.comp f * g₂.comp f :=
rfl
```

-- snippet 26
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.nonnegHomClass (L65-L67)
instance nonnegHomClass : NonnegHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with apply_nonneg := fun f => f.nonneg' }
```

-- snippet 27
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.mulHomClass (L62-L64)
instance mulHomClass : MulHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_mul := fun f => f.map_mul' }
```

-- snippet 28
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.ext (L76-L79)
theorem ext ⦃f g : AbsoluteValue R S⦄ : (∀ x, f x = g x) → f = g :=
DFunLike.ext _ _

/-- See Note [custom simps projection]. -/
```

-- snippet 29
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_eq_zero (L426-L427)
lemma abv_eq_zero {x} : abv x = 0 ↔ x = 0 := abv_eq_zero'
```

-- snippet 30
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidWithZeroHom (L165-L167)
def toMonoidWithZeroHom : R →*₀ S :=
abv
```

-- snippet 31
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.subadditiveHomClass (L68-L70)
instance subadditiveHomClass : SubadditiveHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_add_le_add := fun f => f.add_le' }
```

-- snippet 32
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_pos (L451-L459)
theorem abv_pos {a : R} : 0 < abv a ↔ a ≠ 0 :=
(toAbsoluteValue abv).pos_iff

end OrderedSemiring

section LinearOrderedRing

variable {S : Type*} [Ring S] [LinearOrder S] [IsStrictOrderedRing S]
```

-- snippet 33
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_right_inj_of_ne_top (L195-L197)
lemma sub_right_inj_of_ne_top (h : a ≠ ⊤) : a - b = a - c ↔ b = c :=
(sub_right_injective_of_ne_top h).eq_iff
```

-- snippet 34
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_one' (L537-L541)
theorem abv_one' : abv 1 = 1 :=
(toAbsoluteValue abv).map_one_of_isLeftRegular <|
    (IsRegular.of_ne_zero <| (toAbsoluteValue abv).ne_zero one_ne_zero).left

/-- An absolute value as a monoid with zero homomorphism, assuming the target is a semifield. -/
```

-- snippet 35
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidHom (L177-L179)
theorem coe_toMonoidHom : ⇑abv.toMonoidHom = abv :=
rfl
```

-- snippet 36
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidWithZeroHom (L169-L172)
theorem coe_toMonoidWithZeroHom : ⇑abv.toMonoidWithZeroHom = abv :=
rfl

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*` and `1`. -/
```

-- snippet 37
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMulHom (L86-L88)
theorem coe_toMulHom : ⇑abv.toMulHom = abv :=
rfl
```

-- snippet 38
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_sub_le (L491-L493)
theorem abv_sub_le (a b c : R) : abv (a - c) ≤ abv (a - b) + abv (b - c) := by
simpa [sub_eq_add_neg, add_assoc] using abv_add abv (a - b) (b - c)
```

-- snippet 39
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.eq_on_nat_iff_eq_on_int (L256-L268)
lemma eq_on_nat_iff_eq_on_int {f g : AbsoluteValue R S} :
    (∀ n : ℕ, f n = g n) ↔ ∀ n : ℤ, f n = g n := by
refine ⟨fun h z ↦ ?_, fun a n ↦ mod_cast a n⟩
  obtain ⟨n, rfl | rfl⟩ := Int.eq_nat_or_neg z <;> simp [h n]

end OrderedCommRing

section LinearOrderedRing

variable {R S : Type*} [Semiring R] [Ring S] [LinearOrder S] [IsStrictOrderedRing S]
  (abv : AbsoluteValue R S)

/-- `AbsoluteValue.abs` is `abs` as a bundled `AbsoluteValue`. -/
```

-- snippet 40
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_right_strictMono_of_ne_top (L85-L87)
lemma add_right_strictMono_of_ne_top (h : b ≠ ⊤) : StrictMono (fun x ↦ b + x) :=
add_right_mono.strictMono_of_injective <| add_right_injective_of_ne_top _ h
```

-- snippet 41
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_sub_eq_zero_iff (L141-L154)
theorem map_sub_eq_zero_iff (a b : R) : abv (a - b) = 0 ↔ a = b :=
abv.eq_zero.trans sub_eq_zero

end Ring

section Semiring

section IsDomain

-- all of these are true for `NoZeroDivisors S`; but it doesn't work smoothly with the
-- `IsDomain`/`IsCancelMulZero` API
variable {R S : Type*} [Semiring R] [Semiring S] [PartialOrder S] (abv : AbsoluteValue R S)
variable [IsDomain S] [Nontrivial R]
```

-- snippet 42
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_nat_le_self (L186-L206)
lemma apply_nat_le_self [IsOrderedRing S] (n : ℕ) : abv n ≤ n := by
cases subsingleton_or_nontrivial R
  · simp [Subsingleton.eq_zero (n : R)]
  induction n with
  | zero => simp
  | succ n ih =>
  · grw [Nat.cast_succ, Nat.cast_succ, abv.add_le, abv.map_one, ih]

end IsDomain

end Semiring

end OrderedSemiring

section OrderedRing

section Ring

variable {R S : Type*} [Ring R] [Ring S] [PartialOrder S] [IsOrderedRing S]
  (abv : AbsoluteValue R S)
```

-- snippet 43
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_neg (L505-L507)
theorem abv_neg (a : R) : abv (-a) = abv a :=
(toAbsoluteValue abv).map_neg a
```

-- snippet 44
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_add_cancel_right_of_ne_top (L128-L130)
lemma neg_add_cancel_right_of_ne_top (hb : b ≠ ⊤) (a : α) : a + -b + b = a := by
simp [add_assoc, neg_add_cancel_of_ne_top hb]
```

-- snippet 45
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.listSum_le (L102-L106)
lemma listSum_le [AddLeftMono S] (l : List R) : abv l.sum ≤ (l.map abv).sum := by
induction l with
  | nil => simp
  | cons head tail ih => exact (abv.add_le ..).trans <| add_le_add_right ih (abv head)
```

-- snippet 46
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.not_isNontrivial_iff (L350-L356)
lemma not_isNontrivial_iff (v : AbsoluteValue R S) :
    ¬ v.IsNontrivial ↔ ∀ x ≠ 0, v x = 1 := by
simp only [IsNontrivial]
  push Not
  rfl

omit [IsOrderedRing S] in
```

-- snippet 47
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_left_injective_of_ne_top (L68-L70)
lemma add_left_injective_of_ne_top (b : α) (h : b ≠ ⊤) : Function.Injective (fun x ↦ x + b) :=
(IsAddRegular.of_ne_top h).2
```

-- snippet 48
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abvHom' (L542-L556)
def abvHom' : R →*₀ S where
  toFun := abv; map_zero' := abv_zero abv; map_one' := abv_one' abv; map_mul' := abv_mul abv
end Semiring

end IsCancelMulZero

section LinearOrderedSemifield

variable {S : Type*} [Semifield S] [LinearOrder S]

section DivisionSemiring

variable {R : Type*} [DivisionSemiring R] (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 49
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_nonneg (L412-L417)
lemma abv_nonneg (x) : 0 ≤ abv x := abv_nonneg' x
open Lean Meta Mathlib Meta Positivity Qq in
/-- The `positivity` extension which identifies expressions of the form `abv a`.
For performance reasons, we only attempt to apply this when `abv` is a variable.
If it is an explicit function, e.g. `|_|` or `‖_‖`, another extension should apply. -/
```

-- snippet 50
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial (L300-L317)
def trivial : AbsoluteValue R S where
  toFun x := if x = 0 then 0 else 1
map_mul' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp [hx, hy]
  nonneg' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  eq_zero' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  add_le' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp only [hx, ↓reduceIte, hy, one_add_one_eq_two]
    rcases eq_or_ne (x + y) 0 with hxy | hxy <;> simp [hxy, one_le_two]
```

-- snippet 51
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toAbsoluteValue (L441-L447)
def toAbsoluteValue : AbsoluteValue R S where
  toFun := abv
add_le' := abv_add'
  eq_zero' _ := abv_eq_zero'
  nonneg' := abv_nonneg'
  map_mul' := abv_mul'
```

-- snippet 52
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_left_injective_of_ne_top (L184-L186)
lemma sub_left_injective_of_ne_top (h : b ≠ ⊤) : Function.Injective fun x ↦ x - b := by
simpa [sub_eq_add_neg] using add_left_injective_of_ne_top (-b) (by simpa)
```

-- snippet 53
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_right_injective_of_ne_top (L71-L73)
lemma add_right_injective_of_ne_top (b : α) (h : b ≠ ⊤) : Function.Injective (fun x ↦ b + x) :=
(IsAddRegular.of_ne_top h).1
```

-- snippet 54
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_right_injective_of_ne_top (L187-L189)
lemma sub_right_injective_of_ne_top (h : b ≠ ⊤) : Function.Injective fun x ↦ b - x := by
simpa [sub_eq_add_neg] using (add_right_injective_of_ne_top b h).comp neg_injective
```

-- snippet 55
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_mul (L430-L432)
lemma abv_mul (x y) : abv (x * y) = abv x * abv y := abv_mul' x y
/-- A bundled absolute value is an absolute value. -/
```

-- snippet 56
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Euclidean.map_lt_map_iff (L50-L52)
theorem map_lt_map_iff {x y : R} (h : abv.IsEuclidean) : abv x < abv y ↔ x ≺ y :=
map_lt_map_iff' h
```

-- snippet 57
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abs_abv_sub_le_abv_sub (L288-L299)
theorem abs_abv_sub_le_abv_sub (a b : R) : abs (abv a - abv b) ≤ abv (a - b) :=
abs_sub_le_iff.2 ⟨abv.le_sub _ _, by rw [abv.map_sub]; apply abv.le_sub⟩

end LinearOrderedCommRing

section trivial

variable {R : Type*} [Semiring R] [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R]
variable {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S] [Nontrivial S]

/-- The *trivial* absolute value takes the value `1` on all nonzero elements. -/
protected
```

-- snippet 58
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_self_nonneg (L236-L240)
lemma sub_self_nonneg : 0 ≤ a - a := by
obtain rfl | ha := eq_or_ne a ⊤
  · simp
  · rw [sub_self_eq_zero_of_ne_top ha]
```

-- snippet 59
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.IsNontrivial (L335-L337)
def IsNontrivial (v : AbsoluteValue R S) : Prop :=
∃ x ≠ 0, v x ≠ 1
```

-- snippet 60
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_div (L560-L567)
theorem abv_div (a b : R) : abv (a / b) = abv a / abv b :=
map_div₀ (abvHom' abv) a b

end DivisionSemiring

end LinearOrderedSemifield

end IsAbsoluteValue
```

-- snippet 61
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_lt_add_iff_right_of_ne_top (L101-L109)
lemma add_lt_add_iff_right_of_ne_top (h : a ≠ ⊤) : a + b < a + c ↔ b < c :=
(add_right_strictMono_of_ne_top h).lt_iff_lt

end LinearOrderedAddCommMonoidWithTop

namespace LinearOrderedAddCommGroupWithTop

variable [LinearOrderedAddCommGroupWithTop α] {a b c : α}
```

-- snippet 62
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.not_isNontrivial_apply (L358-L368)
lemma not_isNontrivial_apply {v : AbsoluteValue R S} (hv : ¬ v.IsNontrivial) {x : R} (hx : x ≠ 0) :
    v x = 1 :=
v.not_isNontrivial_iff.mp hv _ hx

end OrderedSemiring

section LinearOrderedSemifield

variable [Field R] [Semifield S] [LinearOrder S] [IsStrictOrderedRing S] [ExistsAddOfLE S]
  {v : AbsoluteValue R S}
```

-- snippet 63
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_add (L428-L429)
lemma abv_add (x y) : abv (x + y) ≤ abv x + abv y := abv_add' x y
```

-- snippet 64
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_pos (L232-L234)
lemma neg_pos : 0 < -a ↔ a < 0 ∨ a = ⊤ := by
simpa using sub_pos (a := 0) (b := a)
```

-- snippet 65
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_le_add_iff_left_of_ne_top (L89-L91)
lemma add_le_add_iff_left_of_ne_top (h : a ≠ ⊤) : b + a ≤ c + a ↔ b ≤ c :=
(add_left_strictMono_of_ne_top h).le_iff_le
```

-- snippet 66
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.monoidWithZeroHomClass (L159-L164)
instance monoidWithZeroHomClass : MonoidWithZeroHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.mulHomClass with
    map_zero := fun f => f.map_zero
    map_one := fun f => f.map_one }

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*`, `0` and `1`. -/
```

-- snippet 67
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_sub (L508-L520)
theorem abv_sub (a b : R) : abv (a - b) = abv (b - a) :=
(toAbsoluteValue abv).map_sub a b

end OrderedCommRing

section LinearOrderedCommRing

variable {S : Type*} [CommRing S] [LinearOrder S] [IsStrictOrderedRing S]

section Ring

variable {R : Type*} [Ring R] (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 68
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_inv (L557-L559)
theorem abv_inv (a : R) : abv a⁻¹ = (abv a)⁻¹ :=
map_inv₀ (abvHom' abv) a
```

-- snippet 69
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_left_strictMono_of_ne_top (L82-L84)
lemma add_left_strictMono_of_ne_top (h : b ≠ ⊤) : StrictMono (fun x ↦ x + b) :=
add_left_mono.strictMono_of_injective <| add_left_injective_of_ne_top _ h
```

-- snippet 70
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.sub_le_add (L235-L237)
lemma sub_le_add (a b : R) : abv (a - b) ≤ abv a + abv b := by
simpa only [← sub_eq_add_neg, AbsoluteValue.map_neg] using abv.add_le a (-b)
```

-- snippet 71
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abvHom (L478-L480)
def abvHom [Nontrivial R] : R →*₀ S :=
(toAbsoluteValue abv).toMonoidWithZeroHom
```

-- snippet 72
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_lt_sub_iff_left_of_ne_top (L212-L214)
lemma sub_lt_sub_iff_left_of_ne_top (h : a ≠ ⊤) : b - a < c - a ↔ b < c :=
(sub_left_strictMono_of_ne_top h).lt_iff_lt
```

-- snippet 73
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_left_inj_of_ne_top (L75-L77)
lemma add_left_inj_of_ne_top (h : a ≠ ⊤) : b + a = c + a ↔ b = c :=
(add_left_injective_of_ne_top _ h).eq_iff
```

-- snippet 74
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_right_inj_of_ne_top (L79-L81)
lemma add_right_inj_of_ne_top (h : a ≠ ⊤) : a + b = a + c ↔ b = c :=
(add_right_injective_of_ne_top _ h).eq_iff
```

-- snippet 75
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.Simps (L80-L84)
def Simps.apply (f : AbsoluteValue R S) : R → S :=
f

initialize_simps_projections AbsoluteValue (toFun → apply)
```

-- snippet 76
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_top (L62-L64)
theorem add_top (a : α) : a + ⊤ = ⊤ :=
Trans.trans (add_comm _ _) (top_add _)
```

-- snippet 77
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_one (L474-L477)
theorem abv_one [Nontrivial R] : abv 1 = 1 :=
(toAbsoluteValue abv).map_one

/-- `abv` as a `MonoidWithZeroHom`. -/
```

-- snippet 78
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_le_sub_iff_left_of_ne_top (L208-L210)
lemma sub_le_sub_iff_left_of_ne_top (h : a ≠ ⊤) : b - a ≤ c - a ↔ b ≤ c :=
(sub_left_strictMono_of_ne_top h).le_iff_le
```

-- snippet 79
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.top_add (L58-L60)
theorem top_add (a : α) : ⊤ + a = ⊤ :=
LinearOrderedAddCommMonoidWithTop.top_add' a
```

-- snippet 80
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_pos (L226-L230)
lemma sub_pos : 0 < a - b ↔ b < a ∨ b = ⊤ := by
obtain rfl | hb := eq_or_ne b ⊤
  · simp
  · simp [← sub_self_eq_zero_of_ne_top hb, hb]
```

-- snippet 81
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_left_strictMono_of_ne_top (L204-L206)
lemma sub_left_strictMono_of_ne_top (h : b ≠ ⊤) : StrictMono fun x ↦ x - b := by
simpa [sub_eq_add_neg] using add_left_strictMono_of_ne_top (b := -b) (by simpa)
```

-- snippet 82
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_lt_add_iff_left_of_ne_top (L97-L99)
lemma add_lt_add_iff_left_of_ne_top (h : a ≠ ⊤) : b + a < c + a ↔ b < c :=
(add_left_strictMono_of_ne_top h).lt_iff_lt
```

-- snippet 83
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_pow (L481-L490)
theorem abv_pow [Nontrivial R] (abv : R → S) [IsAbsoluteValue abv] (a : R) (n : ℕ) :
    abv (a ^ n) = abv a ^ n :=
(toAbsoluteValue abv).map_pow a n

end Semiring

section Ring

variable {R : Type*} [Ring R] (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 84
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_neg_cancel_left_of_ne_top (L119-L121)
lemma add_neg_cancel_left_of_ne_top (ha : a ≠ ⊤) (b : α) : a + (-a + b) = b := by
simp [← add_assoc, add_neg_cancel_of_ne_top ha]
```

-- snippet 85
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_natAbs_eq (L250-L255)
lemma apply_natAbs_eq (x : ℤ) : abv (natAbs x) = abv x := by
obtain ⟨_, rfl | rfl⟩ := Int.eq_nat_or_neg x <;> simp

open Int in
/-- Values of an absolute value coincide on the image of `ℕ` in `R`
if and only if they coincide on the image of `ℤ` in `R`. -/
```

-- snippet 86
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidHom (L173-L175)
def toMonoidHom : R →* S :=
abv
```

-- snippet 87
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.funLike (L55-L58)
instance funLike : FunLike (AbsoluteValue R S) R S where
  coe f := f.toFun
coe_injective' f g h := by obtain ⟨⟨_, _⟩, _⟩ := f; obtain ⟨⟨_, _⟩, _⟩ := g; congr
```

-- snippet 88
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_ne_top (L149-L150)
lemma add_ne_top : a + b ≠ ⊤ ↔ a ≠ ⊤ ∧ b ≠ ⊤ := by simp [← isAddUnit_iff]
```

-- snippet 89
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.addGroupSeminormClass (L238-L242)
instance addGroupSeminormClass : AddGroupSeminormClass (AbsoluteValue R S) R S where
  toSubadditiveHomClass := AbsoluteValue.subadditiveHomClass
map_zero := AbsoluteValue.map_zero
  map_neg_eq_map f a := AbsoluteValue.map_neg f a
```

-- snippet 90
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_one_of_isLeftRegular (L124-L126)
theorem map_one_of_isLeftRegular (h : IsLeftRegular (abv 1)) : abv 1 = 1 :=
h <| by simp [← abv.map_mul]
```

-- snippet 91
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_add_cancel_of_ne_top (L116-L118)
lemma neg_add_cancel_of_ne_top (ha : a ≠ ⊤) : -a + a = 0 := by
simp [add_comm, add_neg_cancel_of_ne_top ha]
```

-- snippet 92
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abs_isAbsoluteValue (L460-L473)
instance abs_isAbsoluteValue : IsAbsoluteValue (abs : S → S) :=
AbsoluteValue.abs.isAbsoluteValue

end LinearOrderedRing

section OrderedRing

variable {S : Type*} [Ring S] [PartialOrder S]

section Semiring

variable {R : Type*} [Semiring R] (abv : R → S) [IsAbsoluteValue abv]
variable [IsDomain S]
```

-- snippet 93
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_self_eq_zero_iff_ne_top (L221-L225)
lemma sub_self_eq_zero_iff_ne_top : a - a = 0 ↔ a ≠ ⊤ := by
rw [sub_eq_add_neg, add_neg_cancel_iff_ne_top]

alias ⟨_, sub_self_eq_zero_of_ne_top⟩ := sub_self_eq_zero_iff_ne_top
```

-- snippet 94
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial_apply (L319-L334)
lemma trivial_apply {x : R} (hx : x ≠ 0) : AbsoluteValue.trivial (S := S) x = 1 :=
if_neg hx

end trivial

section nontrivial

section OrderedSemiring

variable {R : Type*} [Semiring R] {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S]

/-- An absolute value on a semiring `R` without zero divisors is *nontrivial* if it takes
a value `≠ 1` on a nonzero element.

This has the advantage over `v ≠ .trivial` that it does not require decidability
of `· = 0` in `R`. -/
```

-- snippet 95
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Euclidean.sub_mod_lt (L55-L74)
theorem sub_mod_lt (h : abv.IsEuclidean) (a : R) {b : R} (hb : b ≠ 0) : abv (a % b) < abv b :=
h.map_lt_map_iff.mpr (EuclideanDomain.mod_lt a hb)

end IsEuclidean

end OrderedSemiring

section Int

open Int

-- TODO: generalize to `LinearOrderedEuclideanDomain`s if we ever get a definition of those
/-- `abs : ℤ → ℤ` is a Euclidean absolute value -/
protected theorem abs_isEuclidean : IsEuclidean (AbsoluteValue.abs : AbsoluteValue ℤ ℤ) :=
  { map_lt_map_iff' := fun {x y} =>
       show abs x < abs y ↔ natAbs x < natAbs y by rw [abs_eq_natAbs, abs_eq_natAbs, ofNat_lt] }

end Int

end AbsoluteValue
```

-- snippet 96
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_le_add_iff_right_of_ne_top (L93-L95)
lemma add_le_add_iff_right_of_ne_top (h : a ≠ ⊤) : a + b ≤ a + c ↔ b ≤ c :=
(add_right_strictMono_of_ne_top h).le_iff_le
```

-- snippet 97
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abv_zero (L448-L450)
theorem abv_zero : abv 0 = 0 :=
(toAbsoluteValue abv).map_zero
```

-- snippet 98
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_neg_cancel_iff_ne_top (L216-L219)
lemma add_neg_cancel_iff_ne_top : a + -a = 0 ↔ a ≠ ⊤ where
  mp := by contrapose; simp +contextual
mpr h := add_neg_cancel_of_ne_top h
```

-- snippet 99
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_mk (L72-L74)
theorem coe_mk (f : R →ₙ* S) {h₁ h₂ h₃} : (AbsoluteValue.mk f h₁ h₂ h₃ : R → S) = f :=
rfl
```

-- snippet 100
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.neg_add_cancel_left_of_ne_top (L122-L124)
lemma neg_add_cancel_left_of_ne_top (ha : a ≠ ⊤) (b : α) : -a + (a + b) = b := by
simp [← add_assoc, neg_add_cancel_of_ne_top ha]
```

-- snippet 101
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.isNontrivial_iff_ne_trivial (L338-L349)
lemma isNontrivial_iff_ne_trivial [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R]
    [Nontrivial S] (v : AbsoluteValue R S) :
    v.IsNontrivial ↔ v ≠ .trivial := by
refine ⟨fun ⟨x, hx₀, hx₁⟩ h ↦ hx₁ <| h.symm ▸ trivial_apply hx₀, fun H ↦ ?_⟩
  simp only [IsNontrivial]
  contrapose! H
  ext1 x
  rcases eq_or_ne x 0 with rfl | hx
  · simp
  · simp [H, hx]

omit [IsOrderedRing S] in
```

-- snippet 102
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.zeroHomClass (L59-L61)
instance zeroHomClass : ZeroHomClass (AbsoluteValue R S) R S where
  map_zero f := (f.eq_zero' _).2 rfl
```

-- snippet 103
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.add_neg_cancel_right_of_ne_top (L125-L127)
lemma add_neg_cancel_right_of_ne_top (hb : b ≠ ⊤) (a : α) : a + b + -b = a := by
simp [add_assoc, add_neg_cancel_of_ne_top hb]
```

-- snippet 104
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.sub_abv_le_abv_sub (L494-L504)
theorem sub_abv_le_abv_sub [IsOrderedRing S] (a b : R) : abv a - abv b ≤ abv (a - b) :=
(toAbsoluteValue abv).le_sub a b

end Ring

end OrderedRing

section OrderedCommRing
variable [CommRing S] [PartialOrder S] [IsOrderedRing S] [NoZeroDivisors S] [Ring R]
  (abv : R → S) [IsAbsoluteValue abv]
```

-- snippet 105
```lean
-- Mathlib.Algebra.Order.AddGroupWithTop.sub_left_inj_of_ne_top (L191-L193)
lemma sub_left_inj_of_ne_top (h : a ≠ ⊤) : b - a = c - a ↔ b = c :=
(sub_left_injective_of_ne_top h).eq_iff
```
[/INST]

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