Source code on Github{-# OPTIONS --safe #-}
module Prelude.Semigroup where
open import Prelude.Init; open SetAsType
open import Prelude.Functor
open import Prelude.Setoid
open import Prelude.Lift
record Semigroup (A : Type ℓ) : Type ℓ where
  infixr 5 _◇_ _<>_
  field _◇_ : A → A → A
  _<>_ = _◇_
open Semigroup ⦃...⦄ public
record SemigroupLaws (A : Type ℓ)
  ⦃ _ : Semigroup A ⦄
  
  ⦃ _ : ISetoid A ⦄ ⦃ _ : SetoidLaws A ⦄
  : Type (ℓ ⊔ₗ relℓ) where
  open Alg≈
  field ◇-comm   : Commutative _◇_
        ◇-assocʳ : Associative _◇_
  ◇-assocˡ : ∀ (x y z : A) → (x ◇ (y ◇ z)) ≈ ((x ◇ y) ◇ z)
  ◇-assocˡ x y z = ≈-sym (◇-assocʳ x y z)
open SemigroupLaws ⦃...⦄ public
private variable A : Type ℓ; B : Type ℓ′
module _ where
  instance _ = mkISetoid≡; _ = mkSetoidLaws≡
  SemigroupLaws≡ : (A : Type ℓ) → ⦃ _ : Semigroup A ⦄ → Type ℓ
  SemigroupLaws≡ A = SemigroupLaws A
  module _ ⦃ _ : Semigroup A ⦄ ⦃ _ : SemigroupLaws≡ A ⦄ where
    open SemigroupLaws it public
      renaming (◇-comm to ◇-comm≡; ◇-assocʳ to ◇-assocʳ≡; ◇-assocˡ to ◇-assocˡ≡)
record LawfulSemigroup (A : Type ℓ) ⦃ _ : LawfulSetoid A ⦄ : Typeω where
  field ⦃ is ⦄ : Semigroup A
        ⦃ obeys ⦄ : SemigroupLaws A
instance
  mkLawful-Semigroup :
    ⦃ _ : LawfulSetoid A ⦄ ⦃ _ : Semigroup A ⦄
    → ⦃ SemigroupLaws A ⦄ → LawfulSemigroup A
  mkLawful-Semigroup = record {}
open LawfulSemigroup ⦃...⦄ using () public
record LawfulSemigroup≡ (A : Type ℓ) : Typeω where
  field ⦃ is ⦄ : Semigroup A
        ⦃ obeys ⦄ : SemigroupLaws≡ A
instance
  mkLawful-Semigroup≡ : ⦃ _ : Semigroup A ⦄ → ⦃ SemigroupLaws≡ A ⦄ → LawfulSemigroup≡ A
  mkLawful-Semigroup≡ = record {}
open LawfulSemigroup≡ ⦃...⦄ using () public
instance
  Semigroup-List : Semigroup (List A)
  Semigroup-List ._◇_ = _++_
  
  
  Semigroup-List⁺ : Semigroup (List⁺ A)
  Semigroup-List⁺ ._◇_ = _⁺++⁺_
  Semigroup-∃Vec : Semigroup (∃ (Vec A))
  Semigroup-∃Vec ._◇_ (_ , v) (_ , v′) = _ , (v V.++ v′)
  Semigroup-String : Semigroup String
  Semigroup-String ._◇_ = Str._++_
module _ ⦃ _ : Semigroup A ⦄ ⦃ _ : Semigroup B ⦄ where instance
  Semigroup-× : Semigroup (A × B)
  Semigroup-× ._◇_ (a , b) (a′ , b′) = (a ◇ a′ , b ◇ b′)
  SemigroupLaws-× : ⦃ SemigroupLaws≡ A ⦄ → ⦃ SemigroupLaws≡ B ⦄
                  → SemigroupLaws≡ (A × B)
  SemigroupLaws-× = record {◇-assocʳ = p; ◇-comm = q}
    where
      open Alg≡
      p : Associative (_◇_ {A = A × B})
      p (a , b) (c , d) (e , f) rewrite ◇-assocʳ≡ a c e | ◇-assocʳ≡ b d f = refl
      q : Commutative (_◇_ {A = A × B})
      q (a , b) (c , d) rewrite ◇-comm≡ a c | ◇-comm≡ b d = refl
module _ where instance
  open import Prelude.Setoid.Maybe
  Semigroup-Maybe : ⦃ Semigroup A ⦄ → Semigroup (Maybe A)
  Semigroup-Maybe ._◇_ = λ where
    (just x) (just y) → just (x ◇ y)
    (just x) nothing  → just x
    nothing  m        → m
  SemigroupLaws≡-Maybe : ⦃ _ : Semigroup A ⦄ ⦃ _ : SemigroupLaws≡ A ⦄
    → SemigroupLaws≡ (Maybe A)
  SemigroupLaws≡-Maybe = record
    { ◇-assocʳ = λ where
        (just x) (just y) (just z) → cong just $ ◇-assocʳ≡ x y z
        (just x) (just y) nothing  → refl
        (just x) nothing  z        → refl
        nothing  (just y) z        → refl
        nothing  nothing  z        → refl
    ; ◇-comm = λ where
        (just x) (just y) → cong just $ ◇-comm≡ x y
        (just x) nothing  → refl
        nothing  (just y) → refl
        nothing  nothing  → it
    }
  SemigroupLaws-Maybe :
    
    ⦃ _ : ISetoid A ⦄ ⦃ _ : SetoidLaws A ⦄
    ⦃ _ : LawfulSemigroup A ⦄
    → SemigroupLaws (Maybe A)
  SemigroupLaws-Maybe = record
    { ◇-assocʳ = λ where
        (just x) (just y) (just z) → ◇-assocʳ x y z
        (just x) (just y) nothing  → ≈-refl {x = x ◇ y}
        (just x) nothing  z        → ≈-refl {x = just x ◇ z}
        nothing  (just y) z        → ≈-refl {x = just y ◇ z}
        nothing  nothing  z        → ≈-refl {x = z}
    ; ◇-comm = λ where
        (just x) (just y) → ◇-comm x y
        (just x) nothing  → ≈-refl {x = x}
        nothing  (just y) → ≈-refl {x = y}
        nothing  nothing  → it
    }
instance _ = mkISetoid≡; _ = mkSetoidLaws≡
module _ where
  open Nat
  Semigroup-ℕ-+ = Semigroup ℕ ∋ λ where ._◇_ → _+_
  
  
  
  
  SemigroupLaws-ℕ-+ = SemigroupLaws ℕ ∋
    record {◇-assocʳ = +-assoc; ◇-comm = +-comm}
    where instance _ = Semigroup-ℕ-+
  Semigroup-ℕ-* = Semigroup ℕ ∋ λ where ._◇_ → _*_
  
  
  
  
  SemigroupLaws-ℕ-* = SemigroupLaws ℕ ∋ record {◇-assocʳ = *-assoc; ◇-comm = *-comm}
    where instance _ = Semigroup-ℕ-*
module _ where
  open Integer
  Semigroup-ℤ-+ = Semigroup ℤ ∋ λ where ._◇_ → Integer._+_
  SemigroupLaws-ℤ-+ = SemigroupLaws ℤ ∋
    record {◇-assocʳ = +-assoc; ◇-comm = +-comm}
    where instance _ = Semigroup-ℤ-+
  Semigroup-ℤ-* = Semigroup ℤ ∋ λ where ._◇_ → Integer._*_
  SemigroupLaws-ℤ-* = SemigroupLaws ℤ ∋
    record {◇-assocʳ = *-assoc; ◇-comm = *-comm}
    where instance _ = Semigroup-ℤ-*