{-# OPTIONS --without-K --exact-split --safe #-}
module Fragment.Extensions.CSemigroup.Base where
open import Fragment.Equational.Theory.Bundles
open import Fragment.Algebra.Signature
open import Fragment.Algebra.Free Σ-magma hiding (_~_)
open import Fragment.Algebra.Homomorphism Σ-magma
open import Fragment.Algebra.Algebra Σ-magma
using (Algebra; IsAlgebra; Interpretation; Congruence)
open import Fragment.Equational.FreeExtension Θ-csemigroup
using (FreeExtension; IsFreeExtension)
open import Fragment.Equational.Model Θ-csemigroup
open import Fragment.Extensions.CSemigroup.Monomial
open import Fragment.Setoid.Morphism using (_↝_)
open import Level using (Level; _⊔_)
open import Data.Nat using (ℕ)
open import Data.Fin using (#_)
open import Data.Vec using (Vec; []; _∷_; map)
open import Data.Vec.Relation.Binary.Pointwise.Inductive using ([]; _∷_)
import Relation.Binary.Reasoning.Setoid as Reasoning
open import Relation.Binary using (Setoid; IsEquivalence)
open import Relation.Binary.PropositionalEquality as PE using (_≡_)
private
variable
a ℓ : Level
module _ (A : Model {a} {ℓ}) (n : ℕ) where
private
open module A = Setoid ∥ A ∥/≈
_·_ : ∥ A ∥ → ∥ A ∥ → ∥ A ∥
x · y = A ⟦ • ⟧ (x ∷ y ∷ [])
·-cong : ∀ {x y z w} → x ≈ y → z ≈ w → x · z ≈ y · w
·-cong x≈y z≈w = (A ⟦ • ⟧-cong) (x≈y ∷ z≈w ∷ [])
·-comm : ∀ (x y : ∥ A ∥) → x · y ≈ y · x
·-comm x y = ∥ A ∥ₐ-models comm (env {A = ∥ A ∥ₐ} (x ∷ y ∷ []))
·-assoc : ∀ (x y z : ∥ A ∥) → (x · y) · z ≈ x · (y · z)
·-assoc x y z = ∥ A ∥ₐ-models assoc (env {A = ∥ A ∥ₐ} (x ∷ y ∷ z ∷ []))
data Blob : Set a where
sta : ∥ A ∥ → Blob
dyn : ∥ J' n ∥ → Blob
blob : ∥ J' n ∥ → ∥ A ∥ → Blob
infix 6 _≋_
data _≋_ : Blob → Blob → Set (a ⊔ ℓ) where
sta : ∀ {x y} → x ≈ y → sta x ≋ sta y
dyn : ∀ {xs ys} → xs ≡ ys → dyn xs ≋ dyn ys
blob : ∀ {x y xs ys} → xs ≡ ys → x ≈ y
→ blob xs x ≋ blob ys y
≋-refl : ∀ {x} → x ≋ x
≋-refl {x = sta x} = sta A.refl
≋-refl {x = dyn xs} = dyn PE.refl
≋-refl {x = blob xs x} = blob PE.refl A.refl
≋-sym : ∀ {x y} → x ≋ y → y ≋ x
≋-sym (sta p) = sta (A.sym p)
≋-sym (dyn ps) = dyn (PE.sym ps)
≋-sym (blob ps p) = blob (PE.sym ps) (A.sym p)
≋-trans : ∀ {x y z} → x ≋ y → y ≋ z → x ≋ z
≋-trans (sta p) (sta q) = sta (A.trans p q)
≋-trans (dyn ps) (dyn qs) = dyn (PE.trans ps qs)
≋-trans (blob ps p) (blob qs q) = blob (PE.trans ps qs) (A.trans p q)
≋-isEquivalence : IsEquivalence _≋_
≋-isEquivalence = record { refl = ≋-refl
; sym = ≋-sym
; trans = ≋-trans
}
Blob/≋ : Setoid _ _
Blob/≋ = record { Carrier = Blob
; _≈_ = _≋_
; isEquivalence = ≋-isEquivalence
}
_++_ : Blob → Blob → Blob
sta x ++ sta y = sta (x · y)
dyn xs ++ dyn ys = dyn (xs ⊗ ys)
sta x ++ dyn ys = blob ys x
sta x ++ blob ys y = blob ys (x · y)
dyn xs ++ sta y = blob xs y
dyn xs ++ blob ys y = blob (xs ⊗ ys) y
blob xs x ++ sta y = blob xs (x · y)
blob xs x ++ dyn ys = blob (xs ⊗ ys) x
blob xs x ++ blob ys y = blob (xs ⊗ ys) (x · y)
++-cong : ∀ {x y z w} → x ≋ y → z ≋ w → x ++ z ≋ y ++ w
++-cong (sta p) (sta q) = sta (·-cong p q)
++-cong (dyn ps) (dyn qs) = dyn (⊗-cong ps qs)
++-cong (sta p) (dyn qs) = blob qs p
++-cong (sta p) (blob qs q) = blob qs (·-cong p q)
++-cong (dyn ps) (sta q) = blob ps q
++-cong (dyn ps) (blob qs q) = blob (⊗-cong ps qs) q
++-cong (blob ps p) (sta q) = blob ps (·-cong p q)
++-cong (blob ps p) (dyn qs) = blob (⊗-cong ps qs) p
++-cong (blob ps p) (blob qs q) = blob (⊗-cong ps qs) (·-cong p q)
++-comm : ∀ x y → x ++ y ≋ y ++ x
++-comm (sta x) (sta y) = sta (·-comm x y)
++-comm (dyn xs) (dyn ys) = dyn (⊗-comm xs ys)
++-comm (sta x) (dyn ys) = ≋-refl
++-comm (sta x) (blob ys y) = blob PE.refl (·-comm x y)
++-comm (dyn xs) (sta y) = ≋-refl
++-comm (dyn xs) (blob ys y) = blob (⊗-comm xs ys) A.refl
++-comm (blob xs x) (sta y) = blob PE.refl (·-comm x y)
++-comm (blob xs x) (dyn ys) = blob (⊗-comm xs ys) A.refl
++-comm (blob xs x) (blob ys y) = blob (⊗-comm xs ys) (·-comm x y)
++-assoc : ∀ x y z → (x ++ y) ++ z ≋ x ++ (y ++ z)
++-assoc (sta x) (sta y) (sta z) = sta (·-assoc x y z)
++-assoc (dyn xs) (dyn ys) (dyn zs) = dyn (⊗-assoc xs ys zs)
++-assoc (sta x) (sta y) (dyn zs) = ≋-refl
++-assoc (sta x) (sta y) (blob zs z) = blob PE.refl (·-assoc x y z)
++-assoc (sta x) (dyn ys) (sta z) = ≋-refl
++-assoc (sta x) (dyn ys) (dyn zs) = ≋-refl
++-assoc (sta x) (dyn ys) (blob zs z) = ≋-refl
++-assoc (sta x) (blob ys y) (sta z) = blob PE.refl (·-assoc x y z)
++-assoc (sta x) (blob ys y) (dyn zs) = ≋-refl
++-assoc (sta x) (blob ys y) (blob zs z) = blob PE.refl (·-assoc x y z)
++-assoc (dyn xs) (sta y) (sta z) = ≋-refl
++-assoc (dyn xs) (sta y) (dyn zs) = ≋-refl
++-assoc (dyn xs) (sta y) (blob zs z) = ≋-refl
++-assoc (dyn xs) (dyn ys) (sta z) = ≋-refl
++-assoc (dyn xs) (dyn ys) (blob zs z) = blob (⊗-assoc xs ys zs) A.refl
++-assoc (dyn xs) (blob ys y) (sta z) = ≋-refl
++-assoc (dyn xs) (blob ys y) (dyn zs) = blob (⊗-assoc xs ys zs) A.refl
++-assoc (dyn xs) (blob ys y) (blob zs z) = blob (⊗-assoc xs ys zs) A.refl
++-assoc (blob xs x) (sta y) (sta z) = blob PE.refl (·-assoc x y z)
++-assoc (blob xs x) (sta y) (dyn zs) = ≋-refl
++-assoc (blob xs x) (sta y) (blob zs z) = blob PE.refl (·-assoc x y z)
++-assoc (blob xs x) (dyn ys) (sta z) = ≋-refl
++-assoc (blob xs x) (dyn ys) (dyn zs) = blob (⊗-assoc xs ys zs) A.refl
++-assoc (blob xs x) (dyn ys) (blob zs z) = blob (⊗-assoc xs ys zs) A.refl
++-assoc (blob xs x) (blob ys y) (sta z) = blob PE.refl (·-assoc x y z)
++-assoc (blob xs x) (blob ys y) (dyn zs) = blob (⊗-assoc xs ys zs) A.refl
++-assoc (blob xs x) (blob ys y) (blob zs z) = blob (⊗-assoc xs ys zs) (·-assoc x y z)
Blob⟦_⟧ : Interpretation Blob/≋
Blob⟦ • ⟧ (x ∷ y ∷ []) = x ++ y
Blob⟦_⟧-cong : Congruence Blob/≋ Blob⟦_⟧
Blob⟦ • ⟧-cong (p ∷ q ∷ []) = ++-cong p q
Blob/≋-isAlgebra : IsAlgebra Blob/≋
Blob/≋-isAlgebra = record { ⟦_⟧ = Blob⟦_⟧
; ⟦⟧-cong = Blob⟦_⟧-cong
}
Blob/≋-algebra : Algebra
Blob/≋-algebra =
record { ∥_∥/≈ = Blob/≋
; ∥_∥/≈-isAlgebra = Blob/≋-isAlgebra
}
Blob/≋-models : Models Blob/≋-algebra
Blob/≋-models comm θ = ++-comm (θ (# 0)) (θ (# 1))
Blob/≋-models assoc θ = ++-assoc (θ (# 0)) (θ (# 1)) (θ (# 2))
Blob/≋-isModel : IsModel Blob/≋
Blob/≋-isModel =
record { isAlgebra = Blob/≋-isAlgebra
; models = Blob/≋-models
}
Frex : Model
Frex = record { ∥_∥/≈ = Blob/≋
; isModel = Blob/≋-isModel
}
∣inl∣ : ∥ A ∥ → ∥ Frex ∥
∣inl∣ = sta
∣inl∣-cong : Congruent _≈_ _≋_ ∣inl∣
∣inl∣-cong = sta
∣inl∣⃗ : ∥ A ∥/≈ ↝ ∥ Frex ∥/≈
∣inl∣⃗ = record { ∣_∣ = ∣inl∣
; ∣_∣-cong = ∣inl∣-cong
}
∣inl∣-hom : Homomorphic ∥ A ∥ₐ ∥ Frex ∥ₐ ∣inl∣
∣inl∣-hom • (x ∷ y ∷ []) = ≋-refl
inl : ∥ A ∥ₐ ⟿ ∥ Frex ∥ₐ
inl = record { ∣_∣⃗ = ∣inl∣⃗
; ∣_∣-hom = ∣inl∣-hom
}
∣inr∣ : ∥ J n ∥ → ∥ Frex ∥
∣inr∣ x = dyn (∣ norm ∣ x)
∣inr∣-cong : Congruent ≈[ J n ] _≋_ ∣inr∣
∣inr∣-cong p = dyn (∣ norm ∣-cong p)
∣inr∣⃗ : ∥ J n ∥/≈ ↝ ∥ Frex ∥/≈
∣inr∣⃗ = record { ∣_∣ = ∣inr∣
; ∣_∣-cong = ∣inr∣-cong
}
∣inr∣-hom : Homomorphic ∥ J n ∥ₐ ∥ Frex ∥ₐ ∣inr∣
∣inr∣-hom • (x ∷ y ∷ []) = dyn (∣ norm ∣-hom • (x ∷ y ∷ []))
inr : ∥ J n ∥ₐ ⟿ ∥ Frex ∥ₐ
inr = record { ∣_∣⃗ = ∣inr∣⃗
; ∣_∣-hom = ∣inr∣-hom
}
module _ {b ℓ} (X : Model {b} {ℓ}) where
private
open module X = Setoid ∥ X ∥/≈ renaming (_≈_ to _~_)
_⊕_ : ∥ X ∥ → ∥ X ∥ → ∥ X ∥
x ⊕ y = X ⟦ • ⟧ (x ∷ y ∷ [])
⊕-cong : ∀ {x y z w} → x ~ y → z ~ w → x ⊕ z ~ y ⊕ w
⊕-cong p q = (X ⟦ • ⟧-cong) (p ∷ q ∷ [])
⊕-comm : ∀ (x y : ∥ X ∥) → x ⊕ y ~ y ⊕ x
⊕-comm x y = ∥ X ∥ₐ-models comm (env {A = ∥ X ∥ₐ} (x ∷ y ∷ []))
⊕-assoc : ∀ (x y z : ∥ X ∥) → (x ⊕ y) ⊕ z ~ x ⊕ (y ⊕ z)
⊕-assoc x y z = ∥ X ∥ₐ-models assoc (env {A = ∥ X ∥ₐ} (x ∷ y ∷ z ∷ []))
module _
(f : ∥ A ∥ₐ ⟿ ∥ X ∥ₐ)
(g : ∥ J n ∥ₐ ⟿ ∥ X ∥ₐ)
where
∣resid∣ : ∥ Frex ∥ → ∥ X ∥
∣resid∣ (sta x) = ∣ f ∣ x
∣resid∣ (dyn xs) = ∣ g ∣ (∣ syn ∣ xs)
∣resid∣ (blob xs x) = ∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ f ∣ x
∣resid∣-cong : Congruent _≋_ _~_ ∣resid∣
∣resid∣-cong (sta p) = ∣ f ∣-cong p
∣resid∣-cong (dyn ps) = ∣ g ∣-cong (∣ syn ∣-cong ps)
∣resid∣-cong (blob ps p) =
⊕-cong (∣ g ∣-cong (∣ syn ∣-cong ps)) (∣ f ∣-cong p)
open Reasoning ∥ X ∥/≈
∣resid∣-hom : Homomorphic ∥ Frex ∥ₐ ∥ X ∥ₐ ∣resid∣
∣resid∣-hom • (sta x ∷ sta y ∷ []) = ∣ f ∣-hom • (x ∷ y ∷ [])
∣resid∣-hom • (sta x ∷ dyn ys ∷ []) = ⊕-comm (∣ f ∣ x) _
∣resid∣-hom • (sta x ∷ blob ys y ∷ []) = begin
∣ f ∣ x ⊕ (∣ g ∣ (∣ syn ∣ ys) ⊕ ∣ f ∣ y)
≈⟨ ⊕-cong X.refl (⊕-comm _ (∣ f ∣ y)) ⟩
∣ f ∣ x ⊕ (∣ f ∣ y ⊕ ∣ g ∣ (∣ syn ∣ ys))
≈⟨ X.sym (⊕-assoc (∣ f ∣ x) (∣ f ∣ y) _) ⟩
(∣ f ∣ x ⊕ ∣ f ∣ y) ⊕ ∣ g ∣ (∣ syn ∣ ys)
≈⟨ ⊕-cong (∣ f ∣-hom • (x ∷ y ∷ [])) X.refl ⟩
∣ f ∣ (x · y) ⊕ ∣ g ∣ (∣ syn ∣ ys)
≈⟨ ⊕-comm _ _ ⟩
∣ g ∣ (∣ syn ∣ ys) ⊕ ∣ f ∣ (x · y)
∎
∣resid∣-hom • (dyn xs ∷ sta y ∷ []) = X.refl
∣resid∣-hom • (dyn xs ∷ dyn ys ∷ []) = ∣ g ⊙ syn ∣-hom • (xs ∷ ys ∷ [])
∣resid∣-hom • (dyn xs ∷ blob ys y ∷ []) = begin
∣ g ∣ (∣ syn ∣ xs) ⊕ (∣ g ∣ (∣ syn ∣ ys) ⊕ ∣ f ∣ y)
≈⟨ X.sym (⊕-assoc _ _ (∣ f ∣ y)) ⟩
(∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ g ∣ (∣ syn ∣ ys)) ⊕ ∣ f ∣ y
≈⟨ ⊕-cong (∣ g ⊙ syn ∣-hom • (xs ∷ ys ∷ [])) X.refl ⟩
∣ g ∣ (∣ syn ∣ (xs ⊗ ys)) ⊕ ∣ f ∣ y
∎
∣resid∣-hom • (blob xs x ∷ sta y ∷ []) = begin
(∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ f ∣ x) ⊕ ∣ f ∣ y
≈⟨ ⊕-assoc _ (∣ f ∣ x) (∣ f ∣ y) ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ (∣ f ∣ x ⊕ ∣ f ∣ y)
≈⟨ ⊕-cong X.refl (∣ f ∣-hom • (x ∷ y ∷ [])) ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ f ∣ (x · y)
∎
∣resid∣-hom • (blob xs x ∷ dyn ys ∷ []) = begin
(∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ f ∣ x) ⊕ ∣ g ∣ (∣ syn ∣ ys)
≈⟨ ⊕-assoc _ (∣ f ∣ x) _ ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ (∣ f ∣ x ⊕ ∣ g ∣ (∣ syn ∣ ys))
≈⟨ ⊕-cong X.refl (⊕-comm (∣ f ∣ x) _) ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ (∣ g ∣ (∣ syn ∣ ys) ⊕ ∣ f ∣ x)
≈⟨ X.sym (⊕-assoc _ _ (∣ f ∣ x)) ⟩
(∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ g ∣ (∣ syn ∣ ys)) ⊕ ∣ f ∣ x
≈⟨ ⊕-cong (∣ g ⊙ syn ∣-hom • (xs ∷ ys ∷ [])) X.refl ⟩
∣ g ∣ (∣ syn ∣ (xs ⊗ ys)) ⊕ ∣ f ∣ x
∎
∣resid∣-hom • (blob xs x ∷ blob ys y ∷ []) = begin
(∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ f ∣ x) ⊕ (∣ g ∣ (∣ syn ∣ ys) ⊕ ∣ f ∣ y)
≈⟨ ⊕-assoc _ (∣ f ∣ x) _ ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ (∣ f ∣ x ⊕ (∣ g ∣ (∣ syn ∣ ys) ⊕ ∣ f ∣ y))
≈⟨ ⊕-cong X.refl (X.sym (⊕-assoc (∣ f ∣ x) _ _)) ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ ((∣ f ∣ x ⊕ ∣ g ∣ (∣ syn ∣ ys)) ⊕ ∣ f ∣ y)
≈⟨ ⊕-cong X.refl (⊕-cong (⊕-comm (∣ f ∣ x) _) X.refl) ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ ((∣ g ∣ (∣ syn ∣ ys) ⊕ ∣ f ∣ x) ⊕ ∣ f ∣ y)
≈⟨ ⊕-cong X.refl (⊕-assoc _ (∣ f ∣ x) _) ⟩
∣ g ∣ (∣ syn ∣ xs) ⊕ (∣ g ∣ (∣ syn ∣ ys) ⊕ (∣ f ∣ x ⊕ ∣ f ∣ y))
≈⟨ X.sym (⊕-assoc _ _ _) ⟩
(∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ g ∣ (∣ syn ∣ ys)) ⊕ (∣ f ∣ x ⊕ ∣ f ∣ y)
≈⟨ ⊕-cong (∣ g ⊙ syn ∣-hom • (xs ∷ ys ∷ [])) (∣ f ∣-hom • (x ∷ y ∷ [])) ⟩
∣ g ∣ (∣ syn ∣ (xs ⊗ ys)) ⊕ ∣ f ∣ (x · y)
∎
∣resid∣⃗ : ∥ Frex ∥/≈ ↝ ∥ X ∥/≈
∣resid∣⃗ = record { ∣_∣ = ∣resid∣
; ∣_∣-cong = ∣resid∣-cong
}
_[_,_] : ∥ Frex ∥ₐ ⟿ ∥ X ∥ₐ
_[_,_] = record { ∣_∣⃗ = ∣resid∣⃗
; ∣_∣-hom = ∣resid∣-hom
}
module _ {b ℓ} {X : Model {b} {ℓ}} where
private
open module X = Setoid ∥ X ∥/≈ renaming (_≈_ to _~_)
_⊕_ : ∥ X ∥ → ∥ X ∥ → ∥ X ∥
x ⊕ y = X ⟦ • ⟧ (x ∷ y ∷ [])
⊕-cong : ∀ {x y z w} → x ~ y → z ~ w → x ⊕ z ~ y ⊕ w
⊕-cong p q = (X ⟦ • ⟧-cong) (p ∷ q ∷ [])
⊕-comm : ∀ (x y : ∥ X ∥) → x ⊕ y ~ y ⊕ x
⊕-comm x y = ∥ X ∥ₐ-models comm (env {A = ∥ X ∥ₐ} (x ∷ y ∷ []))
⊕-assoc : ∀ (x y z : ∥ X ∥) → (x ⊕ y) ⊕ z ~ x ⊕ (y ⊕ z)
⊕-assoc x y z = ∥ X ∥ₐ-models assoc (env {A = ∥ X ∥ₐ} (x ∷ y ∷ z ∷ []))
module _
{f : ∥ A ∥ₐ ⟿ ∥ X ∥ₐ}
{g : ∥ J n ∥ₐ ⟿ ∥ X ∥ₐ}
where
commute₁ : X [ f , g ] ⊙ inl ≗ f
commute₁ = X.refl
commute₂ : X [ f , g ] ⊙ inr ≗ g
commute₂ {x} = ∣ g ∣-cong (syn⊙norm≗id {x = x})
module _ {h : ∥ Frex ∥ₐ ⟿ ∥ X ∥ₐ}
(c₁ : h ⊙ inl ≗ f)
(c₂ : h ⊙ inr ≗ g)
where
open Reasoning ∥ X ∥/≈
universal : X [ f , g ] ≗ h
universal {sta x} = X.sym c₁
universal {dyn xs} = begin
∣ g ∣ (∣ syn ∣ xs)
≈⟨ X.sym c₂ ⟩
∣ h ∣ (dyn (∣ norm ∣ (∣ syn ∣ xs)))
≈⟨ ∣ h ∣-cong (dyn norm⊙syn≗id) ⟩
∣ h ∣ (dyn xs)
∎
universal {blob xs x} = begin
∣ g ∣ (∣ syn ∣ xs) ⊕ ∣ f ∣ x
≈⟨ ⊕-cong universal universal ⟩
∣ h ∣ (dyn xs) ⊕ ∣ h ∣ (sta x)
≈⟨ ∣ h ∣-hom • (dyn xs ∷ sta x ∷ []) ⟩
∣ h ∣ (blob xs x)
∎
CSemigroupFrex : FreeExtension
CSemigroupFrex = record { _[_] = Frex
; _[_]-isFrex = isFrex
}
where isFrex : IsFreeExtension Frex
isFrex A n =
record { inl = inl A n
; inr = inr A n
; _[_,_] = _[_,_] A n
; commute₁ = λ {_ _ X f g} → commute₁ A n {X = X} {f} {g}
; commute₂ = λ {_ _ X f g} → commute₂ A n {X = X} {f} {g}
; universal = λ {_ _ X f g h} → universal A n {X = X} {f} {g} {h}
}