    ------------------------------------------------------------------------
    -- The Agda standard library
    --
    -- Consequences of a monomomorphism between right semimodules
    ------------------------------------------------------------------------

    {-# OPTIONS --cubical-compatible --safe #-}

    open import Algebra.Module.Bundles.Raw using (RawRightSemimodule)
    open import Algebra.Module.Morphism.Structures using (IsRightSemimoduleMonomorphism)

    module Algebra.Module.Morphism.RightSemimoduleMonomorphism
      {r a b ℓ₁ ℓ₂} {R : Set r} {M : RawRightSemimodule R a ℓ₁} {N : RawRightSemimodule R b ℓ₂} {⟦_⟧}
      (isRightSemimoduleMonomorphism : IsRightSemimoduleMonomorphism M N ⟦_⟧)
      where

    open IsRightSemimoduleMonomorphism isRightSemimoduleMonomorphism
    private
      module M = RawRightSemimodule M
      module N = RawRightSemimodule N

    open import Algebra.Bundles using (Semiring)
    open import Algebra.Core using (Op₂)
    import Algebra.Module.Definitions.Right as RightDefs
    open import Algebra.Module.Structures  using (IsRightSemimodule)
    open import Algebra.Structures using (IsMagma; IsSemiring)
    open import Function.Base using (flip; _$_)
    open import Level using (Level)
    open import Relation.Binary.Core using (Rel)
    import Relation.Binary.Reasoning.Setoid as SetoidReasoning

    private
      variable
        ℓr : Level
        _≈_ : Rel R ℓr
        _+_ _*_ : Op₂ R
        0# 1# : R

    ------------------------------------------------------------------------
    -- Re-exports

    open import Algebra.Morphism.MonoidMonomorphism
      +ᴹ-isMonoidMonomorphism public
        using ()
        renaming
          ( cong to +ᴹ-cong
          ; assoc to +ᴹ-assoc
          ; comm to +ᴹ-comm
          ; identityˡ to +ᴹ-identityˡ
          ; identityʳ to +ᴹ-identityʳ
          ; identity to +ᴹ-identity
          ; isMagma to +ᴹ-isMagma
          ; isSemigroup to +ᴹ-isSemigroup
          ; isMonoid to +ᴹ-isMonoid
          ; isCommutativeMonoid to +ᴹ-isCommutativeMonoid
          )

    ------------------------------------------------------------------------
    -- Properties

    module _ (+ᴹ-isMagma : IsMagma N._≈ᴹ_ N._+ᴹ_) where

      open IsMagma +ᴹ-isMagma
        using (setoid)
        renaming (∙-cong to +ᴹ-cong′)
      open SetoidReasoning setoid

      module MDefs = RightDefs R M._≈ᴹ_
      module NDefs = RightDefs R N._≈ᴹ_

      *ᵣ-cong : NDefs.Congruent _≈_ N._*ᵣ_ → MDefs.Congruent _≈_ M._*ᵣ_
      *ᵣ-cong *ᵣ-cong {x} {y} {u} {v} x≈ᴹy u≈v = injective $ begin
        ⟦ x M.*ᵣ u ⟧ ≈⟨ *ᵣ-homo u x ⟩
        ⟦ x ⟧ N.*ᵣ u ≈⟨ *ᵣ-cong (⟦⟧-cong x≈ᴹy) u≈v ⟩
        ⟦ y ⟧ N.*ᵣ v ≈˘⟨ *ᵣ-homo v y ⟩
        ⟦ y M.*ᵣ v ⟧ ∎

      *ᵣ-zeroʳ : NDefs.RightZero 0# N.0ᴹ N._*ᵣ_ → MDefs.RightZero 0# M.0ᴹ M._*ᵣ_
      *ᵣ-zeroʳ {0# = 0#} *ᵣ-zeroʳ x = injective $ begin
        ⟦ x M.*ᵣ 0# ⟧ ≈⟨ *ᵣ-homo 0# x ⟩
        ⟦ x ⟧ N.*ᵣ 0# ≈⟨ *ᵣ-zeroʳ ⟦ x ⟧ ⟩
        N.0ᴹ          ≈˘⟨ 0ᴹ-homo ⟩
        ⟦ M.0ᴹ ⟧      ∎

      *ᵣ-distribˡ : N._*ᵣ_ NDefs.DistributesOverˡ _+_ ⟶ N._+ᴹ_ → M._*ᵣ_ MDefs.DistributesOverˡ _+_ ⟶ M._+ᴹ_
      *ᵣ-distribˡ {_+_ = _+_} *ᵣ-distribˡ x m n = injective $ begin
        ⟦ x M.*ᵣ (m + n) ⟧             ≈⟨ *ᵣ-homo (m + n) x ⟩
        ⟦ x ⟧ N.*ᵣ (m + n)             ≈⟨ *ᵣ-distribˡ ⟦ x ⟧ m n ⟩
        ⟦ x ⟧ N.*ᵣ m N.+ᴹ ⟦ x ⟧ N.*ᵣ n ≈˘⟨ +ᴹ-cong′ (*ᵣ-homo m x) (*ᵣ-homo n x) ⟩
        ⟦ x M.*ᵣ m ⟧ N.+ᴹ ⟦ x M.*ᵣ n ⟧ ≈˘⟨ +ᴹ-homo (x M.*ᵣ m) (x M.*ᵣ n) ⟩
        ⟦ x M.*ᵣ m M.+ᴹ x M.*ᵣ n ⟧     ∎

      *ᵣ-identityʳ : NDefs.RightIdentity 1# N._*ᵣ_ → MDefs.RightIdentity 1# M._*ᵣ_
      *ᵣ-identityʳ {1# = 1#} *ᵣ-identityʳ m = injective $ begin
        ⟦ m M.*ᵣ 1# ⟧ ≈⟨ *ᵣ-homo 1# m ⟩
        ⟦ m ⟧ N.*ᵣ 1# ≈⟨ *ᵣ-identityʳ ⟦ m ⟧ ⟩
        ⟦ m ⟧         ∎

      *ᵣ-assoc : NDefs.RightCongruent N._*ᵣ_ → NDefs.Associative _*_ N._*ᵣ_ → MDefs.Associative _*_ M._*ᵣ_
      *ᵣ-assoc {_*_ = _*_} *ᵣ-congʳ *ᵣ-assoc m x y = injective $ begin
        ⟦ m M.*ᵣ x M.*ᵣ y ⟧ ≈⟨ *ᵣ-homo y (m M.*ᵣ x) ⟩
        ⟦ m M.*ᵣ x ⟧ N.*ᵣ y ≈⟨ *ᵣ-congʳ (*ᵣ-homo x m) ⟩
        ⟦ m ⟧ N.*ᵣ x N.*ᵣ y ≈⟨ *ᵣ-assoc ⟦ m ⟧ x y ⟩
        ⟦ m ⟧ N.*ᵣ (x * y)  ≈˘⟨ *ᵣ-homo (x * y) m ⟩
        ⟦ m M.*ᵣ (x * y) ⟧  ∎

      *ᵣ-zeroˡ : NDefs.RightCongruent N._*ᵣ_ → NDefs.LeftZero N.0ᴹ N._*ᵣ_ → MDefs.LeftZero M.0ᴹ M._*ᵣ_
      *ᵣ-zeroˡ *ᵣ-congʳ *ᵣ-zeroˡ x = injective $ begin
        ⟦ M.0ᴹ M.*ᵣ x ⟧ ≈⟨ *ᵣ-homo x M.0ᴹ ⟩
        ⟦ M.0ᴹ ⟧ N.*ᵣ x ≈⟨ *ᵣ-congʳ 0ᴹ-homo ⟩
        N.0ᴹ N.*ᵣ x     ≈⟨ *ᵣ-zeroˡ x ⟩
        N.0ᴹ            ≈˘⟨ 0ᴹ-homo ⟩
        ⟦ M.0ᴹ ⟧        ∎

      *ᵣ-distribʳ : NDefs.RightCongruent N._*ᵣ_ → N._*ᵣ_ NDefs.DistributesOverʳ N._+ᴹ_ → M._*ᵣ_ MDefs.DistributesOverʳ M._+ᴹ_
      *ᵣ-distribʳ *ᵣ-congʳ *ᵣ-distribʳ x m n = injective $ begin
        ⟦ (m M.+ᴹ n) M.*ᵣ x ⟧          ≈⟨ *ᵣ-homo x (m M.+ᴹ n) ⟩
        ⟦ m M.+ᴹ n ⟧ N.*ᵣ x            ≈⟨ *ᵣ-congʳ (+ᴹ-homo m n) ⟩
        (⟦ m ⟧ N.+ᴹ ⟦ n ⟧) N.*ᵣ x      ≈⟨ *ᵣ-distribʳ x ⟦ m ⟧ ⟦ n ⟧ ⟩
        ⟦ m ⟧ N.*ᵣ x N.+ᴹ ⟦ n ⟧ N.*ᵣ x ≈˘⟨ +ᴹ-cong′ (*ᵣ-homo x m) (*ᵣ-homo x n) ⟩
        ⟦ m M.*ᵣ x ⟧ N.+ᴹ ⟦ n M.*ᵣ x ⟧ ≈˘⟨ +ᴹ-homo (m M.*ᵣ x) (n M.*ᵣ x) ⟩
        ⟦ m M.*ᵣ x M.+ᴹ n M.*ᵣ x ⟧     ∎

    ------------------------------------------------------------------------
    -- Structures

    module _ (R-isSemiring : IsSemiring _≈_ _+_ _*_ 0# 1#) where

      private
        R-semiring : Semiring _ _
        R-semiring = record { isSemiring = R-isSemiring }

      isRightSemimodule
        : IsRightSemimodule R-semiring N._≈ᴹ_ N._+ᴹ_ N.0ᴹ N._*ᵣ_
        → IsRightSemimodule R-semiring M._≈ᴹ_ M._+ᴹ_ M.0ᴹ M._*ᵣ_
      isRightSemimodule isRightSemimodule = record
        { +ᴹ-isCommutativeMonoid = +ᴹ-isCommutativeMonoid NN.+ᴹ-isCommutativeMonoid
        ; isPrerightSemimodule = record
          { *ᵣ-cong = *ᵣ-cong NN.+ᴹ-isMagma NN.*ᵣ-cong
          ; *ᵣ-zeroʳ = *ᵣ-zeroʳ NN.+ᴹ-isMagma NN.*ᵣ-zeroʳ
          ; *ᵣ-distribˡ = *ᵣ-distribˡ NN.+ᴹ-isMagma NN.*ᵣ-distribˡ
          ; *ᵣ-identityʳ = *ᵣ-identityʳ NN.+ᴹ-isMagma NN.*ᵣ-identityʳ
          ; *ᵣ-assoc = *ᵣ-assoc NN.+ᴹ-isMagma NN.*ᵣ-congʳ NN.*ᵣ-assoc
          ; *ᵣ-zeroˡ = *ᵣ-zeroˡ NN.+ᴹ-isMagma NN.*ᵣ-congʳ NN.*ᵣ-zeroˡ
          ; *ᵣ-distribʳ = *ᵣ-distribʳ NN.+ᴹ-isMagma NN.*ᵣ-congʳ NN.*ᵣ-distribʳ
          }
        } where module NN = IsRightSemimodule isRightSemimodule