open import SOAS.Common
open import SOAS.Families.Core
open import Categories.Object.Initial
open import SOAS.Coalgebraic.Strength
import SOAS.Metatheory.MetaAlgebra

-- Initial-algebra semantics
module SOAS.Metatheory.Semantics {T : Set}
  (β…€F : Functor 𝔽amiliesβ‚› 𝔽amiliesβ‚›) (β…€:Str : Strength β…€F)
  (𝔛 : Familyβ‚›) (open SOAS.Metatheory.MetaAlgebra β…€F 𝔛)
  (𝕋:Init : Initial 𝕄etaAlgebras)
  where

open import SOAS.Context
open import SOAS.Variable
open import SOAS.Construction.Structure as Structure
open import SOAS.Abstract.Hom
import SOAS.Abstract.Coalgebra as β†’β–‘ ; open β†’β–‘.Sorted
import SOAS.Abstract.Box as β–‘ ; open β–‘.Sorted

open import SOAS.Metatheory.Algebra β…€F

open Strength β…€:Str

private
  variable
    Ξ“ Ξ” Θ Ξ  : Ctx
    Ξ± Ξ² : T
    𝒫 𝒬 π’œ : Familyβ‚›


open Initial 𝕋:Init

open Object βŠ₯ public renaming (𝐢 to 𝕋 ; Λ’ to 𝕋ᡃ)
open MetaAlg 𝕋ᡃ public renaming (π‘Žπ‘™π‘” to π•’π•π•˜ ; π‘£π‘Žπ‘Ÿ to 𝕧𝕒𝕣 ; π‘šπ‘£π‘Žπ‘Ÿ to π•žπ•§π•’π•£ ;
                                  π‘šβ‰ˆβ‚ to π•žβ‰ˆβ‚ ; π‘šβ‰ˆβ‚‚ to π•žβ‰ˆβ‚‚)

module Semantics (π’œα΅ƒ : MetaAlg π’œ) where

  open Morphism (! {π’œ ⋉ π’œα΅ƒ}) public renaming (𝑓 to π•€π•–π•ž ; Λ’β‡’ to π•€π•–π•žα΅ƒβ‡’)
  open MetaAlgβ‡’ π•€π•–π•žα΅ƒβ‡’ public renaming (βŸ¨π‘Žπ‘™π‘”βŸ© to βŸ¨π•’βŸ© ; βŸ¨π‘£π‘Žπ‘ŸβŸ© to βŸ¨π•§βŸ© ; βŸ¨π‘šπ‘£π‘Žπ‘ŸβŸ© to βŸ¨π•žβŸ©)
  open MetaAlg π’œα΅ƒ
  module π’œ = MetaAlg π’œα΅ƒ

  eq : {g h : 𝕋 β‡ΎΜ£ π’œ} (gᡃ : MetaAlgβ‡’ 𝕋ᡃ π’œα΅ƒ g) (hᡃ : MetaAlgβ‡’ 𝕋ᡃ π’œα΅ƒ h) (t : 𝕋 Ξ± Ξ“)
     β†’ g t ≑ h t
  eq {g = g}{h} gᡃ hᡃ t  = !-uniqueβ‚‚ (g ⋉ gᡃ) (h ⋉ hᡃ) {x = t}

  -- The interpretation is equal to any other pointed meta-Ξ›-algebra
  π•€π•–π•ž! : {g : 𝕋 β‡ΎΜ£ π’œ}(gᡃ : MetaAlgβ‡’ 𝕋ᡃ π’œα΅ƒ g)(t : 𝕋 Ξ± Ξ“) β†’ π•€π•–π•ž t ≑ g t
  π•€π•–π•ž! {g = g} gᡃ t = !-unique (g ⋉ gᡃ) {x = t}

-- Corollaries: every meta-algebra endo-homomorphism is the identity, including π•€π•–π•ž
eq-id : {g : 𝕋 β‡ΎΜ£ 𝕋} (gᡃ : MetaAlgβ‡’ 𝕋ᡃ 𝕋ᡃ g) (t : 𝕋 Ξ± Ξ“) β†’
        g t ≑ t
eq-id gᡃ t = Semantics.eq 𝕋ᡃ gᡃ (idᡃ 𝕋ᡃ) t

π•€π•–π•ž-id : {t : 𝕋 Ξ± Ξ“} β†’ Semantics.π•€π•–π•ž 𝕋ᡃ t ≑ t
π•€π•–π•ž-id {t = t} = eq-id (Semantics.π•€π•–π•žα΅ƒβ‡’ 𝕋ᡃ) t