open import Prelude
open import Algebra

module Algebra.Construct.Cayley.OnSet {β„“} {𝑆 : Type β„“} (mon : Monoid 𝑆) (sIsSet : isSet 𝑆) where

open Monoid mon

π’ž : Type β„“
π’ž = Ξ£[ f ⦂ (𝑆 β†’ 𝑆) ] Γ— βˆ€ x β†’ f Ξ΅ βˆ™ x ≑ f x

⟦_β‡“βŸ§ : π’ž β†’ 𝑆
⟦ x β‡“βŸ§ = x .fst Ξ΅

⟦_β‡‘βŸ§ : 𝑆 β†’ π’ž
⟦ x β‡‘βŸ§ .fst = _βˆ™_ x
⟦ x β‡‘βŸ§ .snd y = cong (_βˆ™ y) (βˆ™Ξ΅ x)

β“” : π’ž
β“” .fst = id
β“” .snd = Ξ΅βˆ™

open import Path.Reasoning

_βŠ™_ : π’ž β†’ π’ž β†’ π’ž
(x βŠ™ y) .fst z = x .fst (y .fst z)
(x βŠ™ y) .snd z =
  x .fst (y .fst Ξ΅) βˆ™ z     β‰‘Λ˜βŸ¨ cong (_βˆ™ z) (x .snd (y .fst Ξ΅)) ⟩
  x .fst Ξ΅ βˆ™ y .fst Ξ΅ βˆ™ z   β‰‘βŸ¨ assoc (x .fst Ξ΅) (y .fst Ξ΅) z ⟩
  x .fst Ξ΅ βˆ™ (y .fst Ξ΅ βˆ™ z) β‰‘βŸ¨ cong (x .fst Ξ΅ βˆ™_) (y .snd z)  ⟩
  x .fst Ξ΅ βˆ™ y .fst z       β‰‘βŸ¨ x .snd (y .fst z) ⟩
  x .fst (y .fst z) ∎

open import Data.Sigma.Properties
open import Cubical.Foundations.Everything using (isPropΞ )

π’žβ‰‘ : {x y : π’ž} β†’ fst x ≑ fst y β†’ x ≑ y
π’žβ‰‘ = Σ≑Prop Ξ» _ β†’ isPropΞ  Ξ» _ β†’ sIsSet _ _

βŠ™-assoc : Associative _βŠ™_
βŠ™-assoc _ _ _ = π’žβ‰‘ refl

β“”βŠ™ : βˆ€ x β†’ β“” βŠ™ x ≑ x
β“”βŠ™ _ = π’žβ‰‘ refl

βŠ™β“” : βˆ€ x β†’ x βŠ™ β“” ≑ x
βŠ™β“” _ = π’žβ‰‘ refl

cayleyMonoid : Monoid π’ž
Monoid._βˆ™_ cayleyMonoid = _βŠ™_
Monoid.Ξ΅ cayleyMonoid = β“”
Monoid.assoc cayleyMonoid = βŠ™-assoc
Monoid.Ξ΅βˆ™ cayleyMonoid = β“”βŠ™
Monoid.βˆ™Ξ΅ cayleyMonoid = βŠ™β“”

π’ž-leftInv : βˆ€ x β†’ ⟦ ⟦ x β‡“βŸ§ β‡‘βŸ§ ≑ x
π’ž-leftInv x = π’žβ‰‘ (funExt (snd x))

π’ž-iso : π’ž ⇔ 𝑆
fun π’ž-iso = ⟦_β‡“βŸ§
inv π’ž-iso = ⟦_β‡‘βŸ§
rightInv π’ž-iso = βˆ™Ξ΅
leftInv π’ž-iso = π’ž-leftInv