{-# OPTIONS --cubical --safe --exact-split #-}
module Cubical.Structures.Set.Mon.List where
open import Cubical.Foundations.Everything
open import Cubical.Data.Sigma
open import Cubical.Data.List
open import Cubical.Data.Maybe as Maybe
open import Cubical.Data.Nat
open import Cubical.Data.Nat.Order
open import Cubical.Data.Unit
import Cubical.Data.Empty as ⊥
open import Cubical.Functions.Logic as L
import Cubical.Structures.Set.Mon.Desc as M
import Cubical.Structures.Free as F
open import Cubical.Structures.Sig
open import Cubical.Structures.Str public
open import Cubical.Structures.Tree
open import Cubical.Structures.Eq
open import Cubical.Structures.Arity
open import Cubical.HITs.PropositionalTruncation as P
open import Cubical.Data.Sum as ⊎
private
variable
ℓ : Level
A B : Type ℓ
list-α : sig M.MonSig (List A) -> List A
list-α (M.`e , i) = []
list-α (M.`⊕ , i) = i fzero ++ i fone
𝔏 : {a : Level} {A : Type a} -> M.MonStruct
𝔏 {A = A} = < List A , list-α >
module Free {x y : Level} {A : Type x} {𝔜 : struct y M.MonSig} (isSet𝔜 : isSet (𝔜 .car)) (𝔜-monoid : 𝔜 ⊨ M.MonSEq) where
module 𝔜 = M.MonSEq 𝔜 𝔜-monoid
module _ (f : A -> 𝔜 .car) where
_♯ : List A -> 𝔜 .car
[] ♯ = 𝔜.e
(x ∷ xs) ♯ = f x 𝔜.⊕ (xs ♯)
private
♯-++ : ∀ xs ys -> (xs ++ ys) ♯ ≡ (xs ♯) 𝔜.⊕ (ys ♯)
♯-++ [] ys = sym (𝔜.unitl (ys ♯))
♯-++ (x ∷ xs) ys = cong (f x 𝔜.⊕_) (♯-++ xs ys) ∙ sym (𝔜.assocr (f x) (xs ♯) (ys ♯))
♯-isMonHom : structHom 𝔏 𝔜
fst ♯-isMonHom = _♯
snd ♯-isMonHom M.`e i = 𝔜.e-eta
snd ♯-isMonHom M.`⊕ i = 𝔜.⊕-eta i _♯ ∙ sym (♯-++ (i fzero) (i fone))
private
listEquivLemma : (g : structHom 𝔏 𝔜) -> (x : List A) -> g .fst x ≡ ((g .fst ∘ [_]) ♯) x
listEquivLemma (g , homMonWit) [] = sym (homMonWit M.`e (lookup [])) ∙ 𝔜.e-eta
listEquivLemma (g , homMonWit) (x ∷ xs) =
g (x ∷ xs) ≡⟨ sym (homMonWit M.`⊕ (lookup ([ x ] ∷ xs ∷ []))) ⟩
𝔜 .alg (M.`⊕ , (λ w -> g (lookup ((x ∷ []) ∷ xs ∷ []) w))) ≡⟨ 𝔜.⊕-eta (lookup ([ x ] ∷ xs ∷ [])) g ⟩
g [ x ] 𝔜.⊕ g xs ≡⟨ cong (g [ x ] 𝔜.⊕_) (listEquivLemma (g , homMonWit) xs) ⟩
_ ∎
listEquivLemma-β : (g : structHom 𝔏 𝔜) -> g ≡ ♯-isMonHom (g .fst ∘ [_])
listEquivLemma-β g = structHom≡ 𝔏 𝔜 g (♯-isMonHom (g .fst ∘ [_])) isSet𝔜 (funExt (listEquivLemma g))
listEquiv : structHom 𝔏 𝔜 ≃ (A -> 𝔜 .car)
listEquiv =
isoToEquiv (iso (λ g -> g .fst ∘ [_]) ♯-isMonHom (λ g -> funExt (𝔜.unitr ∘ g)) (sym ∘ listEquivLemma-β))
module Foldr {A : Type ℓ} {B : Type ℓ} {isSetB : isSet B} where
Endo-α : M.MonStruct
car Endo-α = B -> B
alg Endo-α (M.`e , _) = idfun B
alg Endo-α (M.`⊕ , ρ) = ρ fone ∘ ρ fzero
Endo-sat : Endo-α ⊨ M.MonSEq
Endo-sat M.`unitl ρ = refl
Endo-sat M.`unitr ρ = refl
Endo-sat M.`assocr ρ = refl
open Free {A = A} (isSet→ isSetB) Endo-sat
foldr' : (A -> B -> B) -> List A -> B -> B
foldr' f = (f ♯)
module ListDef = F.Definition M.MonSig M.MonEqSig M.MonSEq
list-sat : ∀ {n} {X : Type n} -> < List X , list-α > ⊨ M.MonSEq
list-sat M.`unitl ρ = refl
list-sat M.`unitr ρ = ++-unit-r (ρ fzero)
list-sat M.`assocr ρ = ++-assoc (ρ fzero) (ρ fone) (ρ ftwo)
listDef : ∀ {ℓ ℓ'} -> ListDef.Free ℓ ℓ' 2
F.Definition.Free.F listDef = List
F.Definition.Free.η listDef = [_]
F.Definition.Free.α listDef = list-α
F.Definition.Free.sat listDef = list-sat
F.Definition.Free.isFree listDef isSet𝔜 satMon = (Free.listEquiv isSet𝔜 satMon) .snd
list-⊥ : (List ⊥.⊥) ≃ Unit
list-⊥ = isoToEquiv (iso (λ _ -> tt) (λ _ -> []) (λ _ -> isPropUnit _ _) lemma)
where
lemma : ∀ xs -> [] ≡ xs
lemma [] = refl
lemma (x ∷ xs) = ⊥.rec x
module Membership {ℓ} {A : Type ℓ} (isSetA : isSet A) where
open Free {A = A} isSetHProp (M.⊔-MonStr-MonSEq ℓ)
よ : A -> A -> hProp ℓ
よ x = λ y -> (x ≡ y) , isSetA x y
∈Prop : A -> List A -> hProp ℓ
∈Prop x = (よ x) ♯
_∈_ : A -> List A -> Type ℓ
x ∈ xs = ∈Prop x xs .fst
isProp-∈ : (x : A) -> (xs : List A) -> isProp (x ∈ xs)
isProp-∈ x xs = (∈Prop x xs) .snd
x∈xs : ∀ x xs -> x ∈ (x ∷ xs)
x∈xs x xs = L.inl refl
x∈[x] : ∀ x -> x ∈ [ x ]
x∈[x] x = x∈xs x []
∈-∷ : ∀ x y xs -> x ∈ xs -> x ∈ (y ∷ xs)
∈-∷ x y xs p = L.inr p
∈-++ : ∀ x xs ys -> x ∈ ys -> x ∈ (xs ++ ys)
∈-++ x [] ys p = p
∈-++ x (a ∷ as) ys p = ∈-∷ x a (as ++ ys) (∈-++ x as ys p)
¬∈[] : ∀ x -> (x ∈ []) -> ⊥.⊥
¬∈[] x = ⊥.rec*
x∈[y]→x≡y : ∀ x y -> x ∈ [ y ] -> x ≡ y
x∈[y]→x≡y x y = P.rec (isSetA x y) $ ⊎.rec (idfun _) ⊥.rec*
module Head {ℓ} {A : Type ℓ} where
_⊕_ : Maybe A -> Maybe A -> Maybe A
nothing ⊕ b = b
just a ⊕ b = just a
⊕-unitl : ∀ x -> nothing ⊕ x ≡ x
⊕-unitl x = refl
⊕-unitr : ∀ x -> x ⊕ nothing ≡ x
⊕-unitr nothing = refl
⊕-unitr (just x) = refl
⊕-assocr : ∀ x y z -> (x ⊕ y) ⊕ z ≡ x ⊕ (y ⊕ z)
⊕-assocr nothing y z = refl
⊕-assocr (just x) y z = refl
Maybe-MonStr : M.MonStruct
car Maybe-MonStr = Maybe A
alg Maybe-MonStr (M.`e , _) = nothing
alg Maybe-MonStr (M.`⊕ , i) = i fzero ⊕ i fone
Maybe-MonStr-MonSEq : Maybe-MonStr ⊨ M.MonSEq
Maybe-MonStr-MonSEq M.`unitl ρ = ⊕-unitl (ρ fzero)
Maybe-MonStr-MonSEq M.`unitr ρ = ⊕-unitr (ρ fzero)
Maybe-MonStr-MonSEq M.`assocr ρ = ⊕-assocr (ρ fzero) (ρ fone) (ρ ftwo)
module _ (isSetA : isSet A) where
open Free {A = A} (isOfHLevelMaybe 0 isSetA) Maybe-MonStr-MonSEq
head : List A -> Maybe A
head = just ♯
head-[] : head [] ≡ nothing
head-[] = refl
head-∷ : ∀ x xs -> head (x ∷ xs) ≡ just x
head-∷ _ _ = refl