module Cubical.Algebra.Monoid.Instances.List where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Structure
open import Cubical.Data.List
open import Cubical.Algebra.Monoid
private
variable
ℓ ℓ' : Level
ListMonoid : hSet ℓ → Monoid ℓ
fst (ListMonoid (A , _)) = (List A)
MonoidStr.ε (snd (ListMonoid _)) = []
MonoidStr._·_ (snd (ListMonoid _)) = _++_
MonoidStr.isMonoid (snd (ListMonoid (_ , pf))) = makeIsMonoid (isOfHLevelList 0 pf)
(λ x y z → sym (++-assoc x y z)) ++-unit-r (λ _ → refl)
foldlMonHom : (M : Monoid ℓ) → MonoidHom (ListMonoid (fst M , MonoidStr.is-set (snd M))) M
foldlMonHom m = fn , monoidequiv refl respects∙
where _∙m_ = (MonoidStr._·_ (snd m))
fn : ⟨ ListMonoid (fst m , MonoidStr.is-set (snd m)) ⟩ → ⟨ m ⟩
fn xs = foldl (_∙m_) (MonoidStr.ε (snd m)) xs
∙foldl : (x y : (fst m)) → (xs : List (fst m)) → x ∙m (foldl _∙m_ y xs) ≡ foldl _∙m_ (x ∙m y) xs
∙foldl x y [] = refl
∙foldl x y (x₁ ∷ xs) = x ∙m foldl _∙m_ y (x₁ ∷ xs)
≡⟨ cong (x ∙m_) (sym (∙foldl y x₁ xs)) ⟩
x ∙m (y ∙m foldl _∙m_ x₁ xs)
≡⟨ MonoidStr.·Assoc (snd m) x y (foldl _∙m_ x₁ xs) ⟩
(x ∙m y) ∙m foldl _∙m_ x₁ xs
≡⟨ ∙foldl (x ∙m y) x₁ xs ⟩
foldl _∙m_ (x ∙m y) (x₁ ∷ xs) ∎
fnCons : (x : (fst m)) → (xs : List (fst m)) → x ∙m (fn xs) ≡ (fn (x ∷ xs))
fnCons x [] = MonoidStr.·IdR (snd m) x ∙ sym (MonoidStr.·IdL (snd m) x)
fnCons x (x₁ ∷ xs) = x ∙m (fn (x₁ ∷ xs))
≡⟨ cong (x ∙m_) (sym (fnCons x₁ xs)) ⟩
(x ∙m (x₁ ∙m fn xs))
≡⟨ MonoidStr.·Assoc (m .snd) x x₁ (fn xs) ⟩
((x ∙m x₁) ∙m fn xs)
≡⟨ ∙foldl (x ∙m x₁) ((MonoidStr.ε (snd m))) xs ⟩
foldl _∙m_ ((x ∙m x₁) ∙m (MonoidStr.ε (snd m))) xs
≡⟨ cong (λ l → foldl _∙m_ l xs) (MonoidStr.·IdR (snd m) (x ∙m x₁)) ⟩
foldl _∙m_ x (x₁ ∷ xs)
≡⟨ sym (cong (λ l → foldl _∙m_ l (x₁ ∷ xs)) (MonoidStr.·IdL (snd m) x)) ⟩
fn (x ∷ x₁ ∷ xs) ∎
respects∙ : (xs ys : List (fst m)) → fn (xs ++ ys) ≡ ((fn xs) ∙m (fn ys))
respects∙ [] ys = sym (MonoidStr.·IdL (snd m) (fn ys))
respects∙ xs@(_ ∷ _) [] = cong fn (++-unit-r xs) ∙ sym (MonoidStr.·IdR (snd m) (fn xs))
respects∙ (x ∷ xs) ys@(_ ∷ _) = fn (x ∷ (xs ++ ys))
≡⟨ sym (fnCons x (xs ++ ys)) ⟩
x ∙m (fn (xs ++ ys))
≡⟨ cong (x ∙m_) (respects∙ xs ys) ⟩
x ∙m ((fn xs) ∙m (fn ys))
≡⟨ MonoidStr.·Assoc (snd m) x (fn xs) (fn ys) ⟩
(x ∙m (fn xs)) ∙m (fn ys)
≡⟨ cong (_∙m (fn ys)) (fnCons x xs) ⟩
(fn (x ∷ xs)) ∙m (fn ys) ∎
mapMonHom : {A : hSet ℓ} → {B : hSet ℓ'} → (f : (fst A) → (fst B)) → MonoidHom (ListMonoid A) (ListMonoid B)
mapMonHom f = map f , monoidequiv refl (λ x y → sym (map++ f x y))