\begin{code} {-# OPTIONS --safe #-} open import Algebra open import Prelude open import Path.Reasoning module Data.Weighted.CommutativeMonoid {ℓ} {𝑆 : Type ℓ} (sgp : Semigroup 𝑆) where open import Data.Weighted.Definition sgp open import Data.Weighted.Eliminators sgp open import Data.Weighted.Functor open Semigroup sgp module _ {A : Type a} where infixr 5 _∪_ _∪_ : Weighted A → Weighted A → Weighted A ⟅⟆ ∪ ys = ys (p ▹ x ∷ xs) ∪ ys = p ▹ x ∷ xs ∪ ys com p x q y xs i ∪ ys = com p x q y (xs ∪ ys) i dup p q x xs i ∪ ys = dup p q x (xs ∪ ys) i trunc xs₁ xs₂ p q i j ∪ ys = trunc (xs₁ ∪ ys) (xs₂ ∪ ys) (cong (_∪ ys) p) (cong (_∪ ys) q) i j ∪-assoc : Associative _∪_ ∪-assoc xs ys zs = ⟦ ∪-assoc-alg ys zs ⟧ xs where ∪-assoc-alg : ∀ ys zs → Ψ[ xs ⦂ Weighted A ] ↦ ((xs ∪ ys) ∪ zs ≡ xs ∪ (ys ∪ zs)) ∪-assoc-alg ys zs .fst ⟅⟆ = refl ∪-assoc-alg ys zs .fst (w ▹ x ∷ _ ⟨ P⟨xs⟩ ⟩) = cong (w ▹ x ∷_) P⟨xs⟩ ∪-assoc-alg ys zs .snd = eq-coh ∪-cons : ∀ w x xs ys → w ▹ x ∷ xs ∪ ys ≡ xs ∪ w ▹ x ∷ ys ∪-cons w x xs ys = ⟦ ∪-cons-alg w x ys ⟧ xs where ∪-cons-alg : ∀ w x ys → Ψ[ xs ⦂ Weighted A ] ↦ (w ▹ x ∷ xs ∪ ys ≡ xs ∪ w ▹ x ∷ ys) ∪-cons-alg w x ys .snd = eq-coh ∪-cons-alg w x ys .fst ⟅⟆ = refl ∪-cons-alg p x ys .fst (q ▹ y ∷ xs ⟨ P⟨xs⟩ ⟩) = p ▹ x ∷ q ▹ y ∷ xs ∪ ys ≡⟨ com p x q y _ ⟩ q ▹ y ∷ p ▹ x ∷ xs ∪ ys ≡⟨ cong (q ▹ y ∷_) P⟨xs⟩ ⟩ q ▹ y ∷ xs ∪ p ▹ x ∷ ys ∎ ∪-idʳ : ∀ xs → xs ∪ ⟅⟆ ≡ xs ∪-idʳ = ⟦ ∪-idʳ-alg ⟧ where ∪-idʳ-alg : Ψ[ xs ⦂ Weighted A ] ↦ (xs ∪ ⟅⟆ ≡ xs) ∪-idʳ-alg .snd = eq-coh ∪-idʳ-alg .fst ⟅⟆ = refl ∪-idʳ-alg .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = cong (w ▹ x ∷_) P⟨xs⟩ ∪-com : ∀ xs ys → xs ∪ ys ≡ ys ∪ xs ∪-com xs ys = ⟦ ∪-com-alg ys ⟧ xs where ∪-com-alg : ∀ ys → Ψ[ xs ⦂ Weighted A ] ↦ (xs ∪ ys ≡ ys ∪ xs) ∪-com-alg ys .snd = eq-coh ∪-com-alg ys .fst ⟅⟆ = sym (∪-idʳ ys) ∪-com-alg ys .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = w ▹ x ∷ xs ∪ ys ≡⟨ cong (w ▹ x ∷_) P⟨xs⟩ ⟩ w ▹ x ∷ ys ∪ xs ≡⟨ ∪-cons w x ys xs ⟩ ys ∪ w ▹ x ∷ xs ∎ commutativeMonoid : CommutativeMonoid (Weighted A) commutativeMonoid .CommutativeMonoid.monoid .Monoid._∙_ = _∪_ commutativeMonoid .CommutativeMonoid.monoid .Monoid.ε = ⟅⟆ commutativeMonoid .CommutativeMonoid.monoid .Monoid.assoc = ∪-assoc commutativeMonoid .CommutativeMonoid.monoid .Monoid.ε∙ _ = refl commutativeMonoid .CommutativeMonoid.monoid .Monoid.∙ε = ∪-idʳ commutativeMonoid .CommutativeMonoid.comm = ∪-com infix 4 _⊆_ \end{code} %<*subset> \begin{code} _⊆_ : Weighted A → Weighted A → Type- xs ⊆ ys = xs ∪ ys ≡ ys \end{code} %</subset> \begin{code} ⊆-trans : ∀ xs ys zs → xs ⊆ ys → ys ⊆ zs → xs ⊆ zs ⊆-trans xs ys zs xs⊆ys ys⊆zs = xs ∪ zs ≡˘⟨ cong (xs ∪_) ys⊆zs ⟩ xs ∪ (ys ∪ zs) ≡˘⟨ ∪-assoc xs ys zs ⟩ (xs ∪ ys) ∪ zs ≡⟨ cong (_∪ zs) xs⊆ys ⟩ ys ∪ zs ≡⟨ ys⊆zs ⟩ zs ∎ []⊆ : ∀ xs → ⟅⟆ ⊆ xs []⊆ _ = refl ⊆-cons : ∀ w (x : A) xs ys → xs ⊆ ys → xs ⊆ w ▹ x ∷ ys ⊆-cons w x xs ys xs⊆ys = sym (∪-cons w x xs ys) ; cong (w ▹ x ∷_) xs⊆ys record _⟶W_ (A : Type a) (B : Type b) : Type (ℓ ℓ⊔ a ℓ⊔ b) where no-eta-equality field act-w : 𝑆 → A → Weighted B coh-w : ∀ p q x → act-w p x ∪ act-w q x ≡ act-w (p ∙ q) x open _⟶W_ public infixl 6 _[_]W⊣_ _[_]W⊣_ : 𝑆 → A ⟶W B → A → Weighted B _[_]W⊣_ = flip act-w [_]W-hom : A ⟶W B → A W⟶ Weighted B [ h ]W-hom = record { w-mon = commutativeMonoid ; w-set = trunc ; w-act = act-w h ; w-coh = coh-w h } [_]W↓ : A ⟶W B → Weighted A → Weighted B [ h ]W↓ = W[ [ h ]W-hom ]↓ module _ {A : Type a} {B : Type b} where collect-∪ : (h : A ⟶W B) (xs ys : Weighted A) → [ h ]W↓ (xs ∪ ys) ≡ [ h ]W↓ xs ∪ [ h ]W↓ ys collect-∪ h xs ys = ⟦ alg ⟧ xs where alg : Ψ[ xs ⦂ Weighted A ] ↦ [ h ]W↓ (xs ∪ ys) ≡ [ h ]W↓ xs ∪ [ h ]W↓ ys alg .fst ⟅⟆ = refl alg .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = cong (w [ h ]W⊣ x ∪_) P⟨xs⟩ ; sym (∪-assoc (w [ h ]W⊣ x) ([ h ]W↓ xs) ([ h ]W↓ ys)) alg .snd = eq-coh module ⟶W-Eq {A : Type a} {B : Type b} where ⟶W′ : Type _ ⟶W′ = Σ[ kont ⦂ (𝑆 → A → Weighted B) ] × (∀ p q x → kont p x ∪ kont q x ≡ kont (p ∙ q) x) toSigma : (A ⟶W B) → ⟶W′ toSigma x = x .act-w , x .coh-w fromSigma : ⟶W′ → (A ⟶W B) fromSigma x = record { act-w = x .fst ; coh-w = x .snd } sigma-iso : (A ⟶W B) ⇔ ⟶W′ sigma-iso .fun = toSigma sigma-iso .inv = fromSigma sigma-iso .rightInv x = refl sigma-iso .leftInv x i .act-w = x .act-w sigma-iso .leftInv x i .coh-w = x .coh-w ⟶W-≡ : (x y : A ⟶W B) → (∀ w v → act-w x w v ≡ act-w y w v) → x ≡ y ⟶W-≡ x y p = sym (sigma-iso .leftInv x) ; cong fromSigma (Σ≡Prop (λ _ → isPropΠ λ _ → isPropΠ λ _ → isPropΠ λ _ → trunc _ _) (funExt λ w → funExt (p w))) ; sigma-iso .leftInv y open ⟶W-Eq using (⟶W-≡) public module _ {A : Type a} {B : Type b} where fold-⊕-hom : ∀ (h : A W⟶ B) x y → W[ h ]↓ x W[ h ]⊕ W[ h ]↓ y ≡ W[ h ]↓ (x ∪ y) fold-⊕-hom h xs ys = ⟦ alg ys ⟧ xs where alg : ∀ ys → Ψ[ xs ⦂ Weighted A ] ↦ W[ h ]↓ xs W[ h ]⊕ W[ h ]↓ ys ≡ W[ h ]↓ (xs ∪ ys) alg ys .fst ⟅⟆ = W[ h ]-ε∙ _ alg ys .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = W[ h ]↓ (w ▹ x ∷ xs) W[ h ]⊕ W[ h ]↓ ys ≡⟨⟩ w W[ h ]⊣ x W[ h ]⊕ W[ h ]↓ xs W[ h ]⊕ W[ h ]↓ ys ≡⟨ W[ h ]-assoc _ _ _ ⟩ w W[ h ]⊣ x W[ h ]⊕ (W[ h ]↓ xs W[ h ]⊕ W[ h ]↓ ys) ≡⟨ cong (w W[ h ]⊣ x W[ h ]⊕_) P⟨xs⟩ ⟩ w W[ h ]⊣ x W[ h ]⊕ W[ h ]↓ (xs ∪ ys) ≡⟨⟩ W[ h ]↓ (w ▹ x ∷ xs ∪ ys) ∎ alg ys .snd = prop-coh λ _ → w-set h _ _ fold-ε-hom : (h : A W⟶ B) → W[ h ]↓ ⟅⟆ ≡ W[ h ]-ε fold-ε-hom _ = refl module _ {A : Type a} {B : Type b} {C : Type c} where infixl 9 _W∘_ _W∘_ : B W⟶ C → A ⟶W B → A W⟶ C (b→c W∘ a→b) .w-mon = b→c .w-mon (b→c W∘ a→b) .w-set = b→c .w-set (b→c W∘ a→b) .w-act s x = W[ b→c ]↓ (s [ a→b ]W⊣ x) (b→c W∘ a→b) .w-coh p q x = W[ b→c ]↓ (p [ a→b ]W⊣ x) W[ b→c ]⊕ W[ b→c ]↓ (q [ a→b ]W⊣ x) ≡⟨ fold-⊕-hom b→c (p [ a→b ]W⊣ x) (q [ a→b ]W⊣ x) ⟩ W[ b→c ]↓ (p [ a→b ]W⊣ x ∪ q [ a→b ]W⊣ x) ≡⟨ cong W[ b→c ]↓ (coh-w a→b p q x) ⟩ W[ b→c ]↓ (p ∙ q [ a→b ]W⊣ x) ∎ module _ (b→c : B W⟶ C) (a→b : A ⟶W B) where W-comp-eq : ∀ x → W[ b→c W∘ a→b ]↓ x ≡ W[ b→c ]↓ ([ a→b ]W↓ x) W-comp-eq = ⟦ alg ⟧ where alg : Ψ[ x ⦂ Weighted A ] ↦ W[ b→c W∘ a→b ]↓ x ≡ W[ b→c ]↓ ([ a→b ]W↓ x) alg .fst ⟅⟆ = refl alg .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = W[ b→c W∘ a→b ]↓ (w ▹ x ∷ xs) ≡⟨⟩ W[ b→c ]↓ (w [ a→b ]W⊣ x) W[ b→c ]⊕ W[ b→c W∘ a→b ]↓ xs ≡⟨ cong (W[ b→c ]↓ (w [ a→b ]W⊣ x) W[ b→c ]⊕_) P⟨xs⟩ ⟩ W[ b→c ]↓ (w [ a→b ]W⊣ x) W[ b→c ]⊕ W[ b→c ]↓ ([ a→b ]W↓ xs) ≡⟨ fold-⊕-hom b→c (w [ a→b ]W⊣ x) ([ a→b ]W↓ xs) ⟩ W[ b→c ]↓ (w [ a→b ]W⊣ x ∪ [ a→b ]W↓ xs) ≡⟨⟩ W[ b→c ]↓ ([ a→b ]W↓ (w ▹ x ∷ xs)) ∎ alg .snd = prop-coh λ _ → w-set b→c _ _ W⟶id : A ⟶W A W⟶id .act-w p x = p ▹ x ∷ ⟅⟆ W⟶id .coh-w p q x = dup p q x ⟅⟆ W⟶id-id : (x : Weighted A) → [ W⟶id ]W↓ x ≡ x W⟶id-id = ⟦ alg ⟧ where alg : Ψ[ x ⦂ Weighted A ] ↦ [ W⟶id ]W↓ x ≡ x alg .snd = eq-coh alg .fst ⟅⟆ = refl alg .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = cong (w ▹ x ∷_) P⟨xs⟩ hom-inj : {A : Type a} → (x y : Weighted A) → (∀ {B : Type (ℓ ℓ⊔ a)} (f : A W⟶ B) → W[ f ]↓ x ≡ W[ f ]↓ y) → x ≡ y hom-inj x y p = sym (W⟶id-id x) ; p [ W⟶id ]W-hom ; W⟶id-id y null : Weighted A → Bool null = ⟦ alg ⟧ where alg : Ψ[ x ⦂ Weighted A ] ↦ Bool alg .fst ⟅⟆ = true alg .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = false alg .snd .c-set _ = isSetBool alg .snd .c-dup p q x xs ψ⟨xs⟩ = refl alg .snd .c-com p x q y xs ψ⟨xs⟩ = refl \end{code}