{-# OPTIONS --without-K --exact-split --safe #-} open import Fragment.Algebra.Signature module Fragment.Algebra.Free.Properties (Σ : Signature) where open import Level using (Level) open import Function using (_∘_) open import Fragment.Algebra.Algebra Σ open import Fragment.Algebra.Free.Base Σ open import Fragment.Algebra.Free.Evaluation Σ open import Fragment.Algebra.Free.Monad Σ open import Fragment.Algebra.Homomorphism Σ open import Fragment.Algebra.Quotient Σ open import Fragment.Setoid.Morphism as M hiding (∣_∣; ∣_∣-cong; id; _≗_) open import Data.Fin using (Fin) open import Data.Vec using (Vec; []; _∷_; map) open import Data.Vec.Properties using (map-∘) open import Data.Vec.Relation.Binary.Pointwise.Inductive as PW using (Pointwise; Pointwise-≡⇒≡; []; _∷_) import Relation.Binary.Reasoning.Setoid as Reasoning open import Relation.Binary using (Setoid; Rel; IsEquivalence) open import Relation.Binary.PropositionalEquality as PE using (_≡_) private variable a b c ℓ₁ ℓ₂ ℓ₃ : Level module _ {A : Algebra {a} {ℓ₁}} (h : Free ∥ A ∥/≈ ⟿ A) (inj : ∣ h ∣⃗ · unit M.≗ M.id) where open Setoid ∥ A ∥/≈ open Reasoning ∥ A ∥/≈ mutual map-∣eval∣-universal : ∀ {n} {xs : Vec (Term ∥ A ∥) n} → Pointwise (≈[ A ]) (map ∣ h ∣ xs) (map ∣ eval A ∣ xs) map-∣eval∣-universal {_} {[]} = [] map-∣eval∣-universal {_} {x ∷ xs} = eval-universal {x} ∷ map-∣eval∣-universal {_} {xs} eval-universal : h ≗ eval A eval-universal {atom x} = inj eval-universal {term f xs} = begin ∣ h ∣ (term f xs) ≈⟨ sym (∣ h ∣-hom f xs) ⟩ A ⟦ f ⟧ (map ∣ h ∣ xs) ≈⟨ (A ⟦ f ⟧-cong) map-∣eval∣-universal ⟩ A ⟦ f ⟧ (map ∣ eval A ∣ xs) ≈⟨ ∣ eval A ∣-hom f xs ⟩ ∣ eval A ∣ (term f xs) ∎ module _ {A : Setoid a ℓ₁} {B : Setoid b ℓ₂} (f : A ↝ Herbrand B) where bind-unitₗ : ∣ bind f ∣⃗ · unit M.≗ f bind-unitₗ = Setoid.refl (Herbrand B) module _ {A : Setoid a ℓ₁} where open Setoid ∥ Free A ∥/≈ open Reasoning ∥ Free A ∥/≈ mutual map-∣bind∣-unitʳ : ∀ {n} → {xs : Vec ∥ Free A ∥ n} → Pointwise ≈[ Free A ] (map ∣ bind {B = A} unit ∣ xs) xs map-∣bind∣-unitʳ {xs = []} = [] map-∣bind∣-unitʳ {xs = x ∷ xs} = bind-unitʳ ∷ map-∣bind∣-unitʳ bind-unitʳ : bind {B = A} unit ≗ id bind-unitʳ {atom _} = Setoid.refl (Herbrand A) bind-unitʳ {term f xs} = begin ∣ bind {B = A} unit ∣ (term f xs) ≈⟨ sym (∣ bind unit ∣-hom f xs) ⟩ term f (map ∣ bind {B = A} unit ∣ xs) ≈⟨ term map-∣bind∣-unitʳ ⟩ term f xs ∎ module _ {A : Setoid a ℓ₁} {B : Setoid b ℓ₂} {C : Setoid c ℓ₃} (g : B ↝ Herbrand C) (f : A ↝ Herbrand B) where open Setoid ∥ Free C ∥/≈ open Reasoning ∥ Free C ∥/≈ mutual map-∣bind∣-assoc : ∀ {n} → {xs : Vec ∥ Free A ∥ n} → Pointwise (≈[ Free C ]) (map (∣ bind g ∣ ∘ ∣ bind f ∣) xs) (map ∣ bind (∣ bind g ∣⃗ · f) ∣ xs) map-∣bind∣-assoc {xs = []} = [] map-∣bind∣-assoc {xs = x ∷ xs} = bind-assoc {x} ∷ map-∣bind∣-assoc bind-assoc : bind g ⊙ bind f ≗ bind (∣ bind g ∣⃗ · f) bind-assoc {atom _} = refl bind-assoc {term op xs} = begin ∣ bind g ∣ (∣ bind f ∣ (term op xs)) ≈⟨ sym (∣ bind g ∣-cong (∣ bind f ∣-hom op xs)) ⟩ ∣ bind g ∣ (term op (map ∣ bind f ∣ xs)) ≈⟨ sym (∣ bind g ∣-hom op (map ∣ bind f ∣ xs)) ⟩ term op (map ∣ bind g ∣ (map ∣ bind f ∣ xs)) ≈⟨ sym (term (PW.map reflexive (PW.≡⇒Pointwise-≡ (map-∘ ∣ bind g ∣ ∣ bind f ∣ xs)))) ⟩ term op (map (∣ bind g ∣ ∘ ∣ bind f ∣) xs) ≈⟨ term map-∣bind∣-assoc ⟩ term op (map ∣ bind (∣ bind g ∣⃗ · f) ∣ xs) ≈⟨ ∣ bind (∣ bind g ∣⃗ · f) ∣-hom op xs ⟩ ∣ bind (∣ bind g ∣⃗ · f) ∣ (term op xs) ∎ fmap-id : ∀ {A : Setoid a ℓ₁} → fmap M.id ≗ id fmap-id {A = A} = bind-unitʳ {A = A} module _ {n} (A : Algebra {a} {ℓ₁}) (θ : Env A n) where IsInstantiation : F n ⟿ A → Set _ IsInstantiation f = ∀ x → ∣ f ∣ (atom (dyn x)) ≡ θ x inst-isInstantiation : IsInstantiation (inst A θ) inst-isInstantiation x = PE.refl mutual map-∣inst∣-universal : ∀ {h m} → IsInstantiation h → {xs : Vec ∥ F n ∥ m} → Pointwise ≈[ A ] (map ∣ h ∣ xs) (map ∣ inst A θ ∣ xs) map-∣inst∣-universal p {xs = []} = [] map-∣inst∣-universal {h = h} p {xs = x ∷ xs} = inst-universal {h = h} p ∷ map-∣inst∣-universal {h = h} p inst-universal : ∀ {h} → IsInstantiation h → h ≗ (inst A θ) inst-universal {h} p {x = atom (dyn x)} = Setoid.reflexive ∥ A ∥/≈ (p x) inst-universal {h} p {x = term f xs} = begin ∣ h ∣ (term f xs) ≈⟨ Setoid.sym ∥ A ∥/≈ (∣ h ∣-hom f xs) ⟩ A ⟦ f ⟧ (map ∣ h ∣ xs) ≈⟨ (A ⟦ f ⟧-cong) (map-∣inst∣-universal {h = h} p {xs = xs}) ⟩ A ⟦ f ⟧ (map ∣ inst A θ ∣ xs) ≈⟨ ∣ inst A θ ∣-hom f xs ⟩ ∣ inst A θ ∣ (term f xs) ∎ where open Reasoning ∥ A ∥/≈ module _ {B : Algebra {b} {ℓ₂}} (h : A ⟿ B) where mutual map-∣inst∣-assoc : ∀ {m} {xs : Vec ∥ F n ∥ m} → Pointwise ≈[ B ] (map ∣ h ⊙ inst A θ ∣ xs) (map ∣ inst B (∣ h ∣ ∘ θ) ∣ xs) map-∣inst∣-assoc {xs = []} = [] map-∣inst∣-assoc {xs = x ∷ xs} = inst-assoc {x = x} ∷ map-∣inst∣-assoc inst-assoc : h ⊙ inst A θ ≗ inst B (∣ h ∣ ∘ θ) inst-assoc {atom (dyn _)} = Setoid.refl ∥ B ∥/≈ inst-assoc {term f xs} = begin ∣ h ⊙ inst A θ ∣ (term f xs) ≈⟨ sym (∣ h ⊙ inst A θ ∣-hom f xs) ⟩ B ⟦ f ⟧ (map ∣ h ⊙ inst A θ ∣ xs) ≈⟨ (B ⟦ f ⟧-cong) map-∣inst∣-assoc ⟩ B ⟦ f ⟧ (map ∣ inst B (∣ h ∣ ∘ θ) ∣ xs) ≈⟨ ∣ inst B (∣ h ∣ ∘ θ) ∣-hom f xs ⟩ ∣ inst B (∣ h ∣ ∘ θ) ∣ (term f xs) ∎ where open Setoid ∥ B ∥/≈ open Reasoning ∥ B ∥/≈