{-# OPTIONS --without-K --exact-split --safe #-} open import Fragment.Algebra.Signature module Fragment.Algebra.Free.Evaluation (Σ : Signature) where open import Fragment.Algebra.Free.Monad Σ open import Fragment.Algebra.Algebra Σ open import Fragment.Algebra.Free.Base Σ open import Fragment.Algebra.Homomorphism Σ open import Fragment.Setoid.Morphism as Morphism open import Level using (Level) open import Data.Empty using (⊥) open import Data.Nat using (ℕ; suc) open import Data.Fin using (Fin; zero; suc) open import Data.Vec using (Vec; []; _∷_; map) open import Data.Vec.Relation.Binary.Pointwise.Inductive using (Pointwise; []; _∷_) open import Relation.Binary using (Setoid) import Relation.Binary.PropositionalEquality as PE private variable a b ℓ₁ ℓ₂ : Level module _ (A : Algebra {a} {ℓ₁}) where private open Setoid ∥ A ∥/≈ open import Relation.Binary.Reasoning.Setoid ∥ A ∥/≈ mutual map-∣eval∣ : ∀ {n} → Vec (Term ∥ A ∥) n → Vec ∥ A ∥ n map-∣eval∣ [] = [] map-∣eval∣ (x ∷ xs) = ∣eval∣ x ∷ map-∣eval∣ xs ∣eval∣ : Term ∥ A ∥ → ∥ A ∥ ∣eval∣ (atom x) = x ∣eval∣ (term f xs) = A ⟦ f ⟧ (map-∣eval∣ xs) mutual map-∣eval∣-cong : ∀ {n} {xs ys : Vec (Term ∥ A ∥) n} → Pointwise (_~_ ∥ A ∥/≈) xs ys → Pointwise ≈[ A ] (map-∣eval∣ xs) (map-∣eval∣ ys) map-∣eval∣-cong [] = [] map-∣eval∣-cong (p ∷ ps) = ∣eval∣-cong p ∷ map-∣eval∣-cong ps ∣eval∣-cong : Congruent (_~_ ∥ A ∥/≈) ≈[ A ] ∣eval∣ ∣eval∣-cong (atom p) = p ∣eval∣-cong {x = term op _} (term p) = (A ⟦ op ⟧-cong) (map-∣eval∣-cong p) ∣eval∣⃗ : Herbrand ∥ A ∥/≈ ↝ ∥ A ∥/≈ ∣eval∣⃗ = record { ∣_∣ = ∣eval∣ ; ∣_∣-cong = ∣eval∣-cong } ∣eval∣-args≡map : ∀ {n} {xs : Vec (Term ∥ A ∥) n} → Pointwise _≈_ (map-∣eval∣ xs) (map ∣eval∣ xs) ∣eval∣-args≡map {xs = []} = [] ∣eval∣-args≡map {xs = x ∷ xs} = refl ∷ ∣eval∣-args≡map ∣eval∣-hom : Homomorphic (Free ∥ A ∥/≈) A ∣eval∣ ∣eval∣-hom f [] = refl ∣eval∣-hom f (x ∷ xs) = sym ((A ⟦ f ⟧-cong) (∣eval∣-args≡map {xs = x ∷ xs})) eval : Free ∥ A ∥/≈ ⟿ A eval = record { ∣_∣⃗ = ∣eval∣⃗ ; ∣_∣-hom = ∣eval∣-hom } fold : ∀ {A : Setoid a ℓ₁} (B : Algebra {b} {ℓ₂}) → (A ↝ ∥ B ∥/≈) → Free A ⟿ B fold B f = (eval B) ⊙ bind (unit · f) Env : (A : Algebra {a} {ℓ₁}) → ℕ → Set _ Env A n = Fin n → ∥ A ∥ env : ∀ {A : Algebra {a} {ℓ₁}} {n} → (Γ : Vec ∥ A ∥ n) → Env A n env {A = _} {suc n} (x ∷ _) zero = x env {A = A} {suc n} (_ ∷ xs) (suc i) = env {A = A} xs i module _ {n} {S : Setoid a ℓ₁} (T : Setoid b ℓ₂) (f : S ↝ T) (g : Fin n → Setoid.Carrier T) where private open Setoid S renaming (Carrier to A) using () open Setoid T renaming (Carrier to B) ∣sub∣ : BT A n → B ∣sub∣ (sta x) = Morphism.∣ f ∣ x ∣sub∣ (dyn x) = g x ∣sub∣-cong : Congruent (_≍_ S n) _≈_ ∣sub∣ ∣sub∣-cong (sta p) = Morphism.∣ f ∣-cong p ∣sub∣-cong (dyn q) = reflexive (PE.cong g q) sub : Atoms S n ↝ T sub = record { ∣_∣ = ∣sub∣ ; ∣_∣-cong = ∣sub∣-cong } module _ {n} {A : Setoid a ℓ₁} (B : Algebra {b} {ℓ₂}) (f : A ↝ ∥ B ∥/≈) (g : Fin n → ∥ B ∥) where subst : Free (Atoms A n) ⟿ B subst = fold B (sub ∥ B ∥/≈ f g) ignore : ∀ (A : Setoid a ℓ₁) → PE.setoid ⊥ ↝ A ignore _ = record { ∣_∣ = λ () ; ∣_∣-cong = λ {} } inst : ∀ {n} (A : Algebra {a} {ℓ₁}) → Env A n → F n ⟿ A inst {n = n} A θ = subst A (ignore ∥ A ∥/≈) θ