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

-- Coalgebraic traversal maps
module SOAS.Metatheory.Coalgebraic {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.Abstract.Hom
import SOAS.Abstract.Coalgebra as โ†’โ–ก ; open โ†’โ–ก.Sorted
import SOAS.Abstract.Box as โ–ก ; open โ–ก.Sorted

open import SOAS.Coalgebraic.Map

open import SOAS.Metatheory.Algebra {T} โ…€F
open import SOAS.Metatheory.Semantics โ…€F โ…€:Str ๐”› ๐•‹:Init
open import SOAS.Metatheory.Traversal โ…€F โ…€:Str ๐”› ๐•‹:Init
open import SOAS.Metatheory.Renaming โ…€F โ…€:Str ๐”› ๐•‹:Init

open Strength โ…€:Str

-- Relationship of traversal and interpretation, assuming ๐’œ has compatible renaming structure
module _ {๐’œ : Familyโ‚›}(๐’œแต‡ : Coalg ๐’œ)(๐’œแตƒ : MetaAlg ๐’œ)
         (open Semantics ๐’œแตƒ)(open Coalg ๐’œแต‡)
         (rแตƒโ‡’ : MetaAlgโ‡’ ๐’œแตƒ (โ–กแตƒ ๐’œแตƒ) r) where

  open MetaAlg ๐’œแตƒ
  open MetaAlgโ‡’ rแตƒโ‡’

  ๐’œแดฎ : Coalgโ‚š ๐’œ
  ๐’œแดฎ = record { แต‡ = ๐’œแต‡ ; ฮท = ๐‘ฃ๐‘Ž๐‘Ÿ ; rโˆ˜ฮท = cong (ฮป - โ†’ - _) โŸจ๐‘ฃ๐‘Ž๐‘ŸโŸฉ }

  -- Interpretation and renaming commute
  ๐•ค๐•–๐•žโˆ˜ren : MapEqโ‚ โ„แดฎ ๐‘Ž๐‘™๐‘” (ฮป t ฯ โ†’ ๐•ค๐•–๐•ž (๐•ฃ๐•–๐•Ÿ t ฯ))
                          (ฮป t ฯ โ†’ r (๐•ค๐•–๐•ž t) ฯ)
  ๐•ค๐•–๐•žโˆ˜ren = record
    { ฯ† = ๐‘ฃ๐‘Ž๐‘Ÿ
    ; ฯ‡ = ๐‘š๐‘ฃ๐‘Ž๐‘Ÿ
    ; fโŸจ๐‘ฃโŸฉ = trans (cong ๐•ค๐•–๐•ž Renaming.๐•ฅโŸจ๐•งโŸฉ) โŸจ๐•งโŸฉ
    ; fโŸจ๐‘šโŸฉ = trans (cong ๐•ค๐•–๐•ž Renaming.๐•ฅโŸจ๐•žโŸฉ) โŸจ๐•žโŸฉ
    ; fโŸจ๐‘ŽโŸฉ = ฮป{ {ฯƒ = ฯƒ}{t} โ†’ begin
          ๐•ค๐•–๐•ž (๐•ฃ๐•–๐•Ÿ (๐•’๐•๐•˜ t) ฯƒ)
      โ‰กโŸจ cong ๐•ค๐•–๐•ž Renaming.๐•ฅโŸจ๐•’โŸฉ โŸฉ
          ๐•ค๐•–๐•ž (๐•’๐•๐•˜ (str โ„แดฎ ๐•‹ (โ…€โ‚ ๐•ฃ๐•–๐•Ÿ t) ฯƒ))
      โ‰กโŸจ โŸจ๐•’โŸฉ โŸฉ
          ๐‘Ž๐‘™๐‘” (โ…€โ‚ ๐•ค๐•–๐•ž (str โ„แดฎ ๐•‹ (โ…€โ‚ ๐•ฃ๐•–๐•Ÿ t) ฯƒ))
      โ‰กห˜โŸจ cong ๐‘Ž๐‘™๐‘” (str-natโ‚‚ ๐•ค๐•–๐•ž (โ…€โ‚ ๐•ฃ๐•–๐•Ÿ t) ฯƒ) โŸฉ
          ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (โ…€.Fโ‚ (ฮป { hโ€ฒ ฯ‚ โ†’ ๐•ค๐•–๐•ž (hโ€ฒ ฯ‚) }) (โ…€โ‚ ๐•ฃ๐•–๐•Ÿ t)) ฯƒ)
      โ‰กห˜โŸจ congr โ…€.homomorphism (ฮป - โ†’ ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ - ฯƒ)) โŸฉ
          ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (โ…€โ‚ (ฮป{ t ฯ โ†’ ๐•ค๐•–๐•ž (๐•ฃ๐•–๐•Ÿ t ฯ)}) t) ฯƒ)
      โˆŽ }
    ; gโŸจ๐‘ฃโŸฉ = trans (rโ‰ˆโ‚ โŸจ๐•งโŸฉ) (cong (ฮป - โ†’ - _) โŸจ๐‘ฃ๐‘Ž๐‘ŸโŸฉ)
    ; gโŸจ๐‘šโŸฉ = trans (rโ‰ˆโ‚ โŸจ๐•žโŸฉ) (cong (ฮป - โ†’ - _) โŸจ๐‘š๐‘ฃ๐‘Ž๐‘ŸโŸฉ)
    ; gโŸจ๐‘ŽโŸฉ = ฮป{ {ฯƒ = ฯƒ}{t} โ†’ begin
          r (๐•ค๐•–๐•ž (๐•’๐•๐•˜ t)) ฯƒ
      โ‰กโŸจ rโ‰ˆโ‚ โŸจ๐•’โŸฉ โŸฉ
          r (๐‘Ž๐‘™๐‘” (โ…€โ‚ ๐•ค๐•–๐•ž t)) ฯƒ
      โ‰กโŸจ cong (ฮป - โ†’ - ฯƒ) โŸจ๐‘Ž๐‘™๐‘”โŸฉ โŸฉ
          ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (โ…€โ‚ r (โ…€โ‚ ๐•ค๐•–๐•ž t)) ฯƒ)
      โ‰กห˜โŸจ congr โ…€.homomorphism (ฮป - โ†’ ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ - ฯƒ)) โŸฉ
          ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (โ…€โ‚ (ฮป{ t ฯ โ†’ r (๐•ค๐•–๐•ž t) ฯ}) t) ฯƒ)
      โˆŽ }
    } where open โ‰ก-Reasoning

  -- Interpretation is a pointed โ–ก-coalgebra homomorphism
  ๐•ค๐•–๐•žแต‡โ‡’ : Coalgโ‡’ ๐•‹แต‡ ๐’œแต‡ ๐•ค๐•–๐•ž
  ๐•ค๐•–๐•žแต‡โ‡’ = record { โŸจrโŸฉ = ฮป{ {t = t} โ†’ MapEqโ‚.โ‰ˆ ๐•ค๐•–๐•žโˆ˜ren t } }

  ๐•ค๐•–๐•žแดฎโ‡’ : Coalgโ‚šโ‡’ ๐•‹แดฎ ๐’œแดฎ ๐•ค๐•–๐•ž
  ๐•ค๐•–๐•žแดฎโ‡’ = record { แต‡โ‡’ = ๐•ค๐•–๐•žแต‡โ‡’ ; โŸจฮทโŸฉ = โŸจ๐•งโŸฉ }

-- Coalgebraic traversal maps
module Travแถœ {๐’ซ ๐’œ : Familyโ‚›}(๐’ซแดฎ : Coalgโ‚š ๐’ซ)(๐‘Ž๐‘™๐‘” : โ…€ ๐’œ โ‡พฬฃ ๐’œ)
               (ฯ† : ๐’ซ โ‡พฬฃ ๐’œ)(ฯ‡ : ๐”› โ‡พฬฃ ใ€– ๐’œ , ๐’œ ใ€—) where
  open Coalgโ‚š ๐’ซแดฎ

  open Traversal ๐’ซแดฎ ๐‘Ž๐‘™๐‘” ฯ† ฯ‡

  -- Traversal is derived from ๐•ค๐•–๐•ž, so it is also a pointed coalgebra homomorphism
  ๐•ฅ๐•ฃ๐•’๐•งแต‡โ‡’ : Coalgโ‡’ ๐•‹แต‡ Travแต‡ ๐•ฅ๐•ฃ๐•’๐•ง
  ๐•ฅ๐•ฃ๐•’๐•งแต‡โ‡’ = ๐•ค๐•–๐•žแต‡โ‡’ Travแต‡ Travแตƒ record
    { โŸจ๐‘Ž๐‘™๐‘”โŸฉ = ฮป{ {t = t} โ†’ dextยฒ (ฮป ฯ ฯ‚ โ†’ cong ๐‘Ž๐‘™๐‘” (str-dist ๐’œ (jแถœ ๐’ซแดฎ) t ฯ ฯ‚)) }
    ; โŸจ๐‘ฃ๐‘Ž๐‘ŸโŸฉ = refl ; โŸจ๐‘š๐‘ฃ๐‘Ž๐‘ŸโŸฉ = refl }

  ๐•ฅ๐•ฃ๐•’๐•งแดฎโ‡’ : Coalgโ‚šโ‡’ ๐•‹แดฎ Travแดฎ ๐•ฅ๐•ฃ๐•’๐•ง
  ๐•ฅ๐•ฃ๐•’๐•งแดฎโ‡’  = record { แต‡โ‡’ = ๐•ฅ๐•ฃ๐•’๐•งแต‡โ‡’ ; โŸจฮทโŸฉ = โŸจ๐•งโŸฉ }

  -- Assuming ๐’œ is also a pointed โ–ก-coalgebra, traversal also commutes with renaming
  module _ (๐’œแดฎ : Coalgโ‚š ๐’œ)(ฯ†แดฎ : Coalgโ‚šโ‡’ ๐’ซแดฎ ๐’œแดฎ ฯ†)
           (๐’œrแตƒ : MetaAlgโ‡’ ๐’œแตƒ (โ–กแตƒ ๐’œแตƒ) (Coalgโ‚š.r ๐’œแดฎ)) where

    private module ๐’œแดฎ = Coalgโ‚š ๐’œแดฎ
    private module ฯ†แดฎ = Coalgโ‚šโ‡’ ฯ†แดฎ
    private module ๐’œrแตƒ = MetaAlgโ‡’ ๐’œrแตƒ

    -- Renaming and interpretation can commute
    rโˆ˜๐•ฅ๐•ฃ๐•’๐•ง : MapEqโ‚‚ ๐’ซแดฎ โ„แดฎ ๐‘Ž๐‘™๐‘” (ฮป t ฯƒ ฯฑ โ†’ ๐’œแดฎ.r (๐•ฅ๐•ฃ๐•’๐•ง t ฯƒ) ฯฑ)
                              (ฮป t ฯƒ ฯฑ โ†’ ๐•ฅ๐•ฃ๐•’๐•ง t (ฮป v โ†’ r (ฯƒ v) ฯฑ))
    rโˆ˜๐•ฅ๐•ฃ๐•’๐•ง = record
      { ฯ† = ๐’œแดฎ.ฮท
      ; ฯ• = ฮป v โ†’ ๐’œแดฎ.r (ฯ† v)
      ; ฯ‡ = ฯ‡
      ; fโŸจ๐‘ฃโŸฉ = ๐’œแดฎ.rโ‰ˆโ‚ ๐•ฅโŸจ๐•งโŸฉ
      ; fโŸจ๐‘šโŸฉ = trans (๐’œแดฎ.rโ‰ˆโ‚ ๐•ฅโŸจ๐•žโŸฉ) (cong (ฮป - โ†’ - _) ๐’œrแตƒ.โŸจ๐‘š๐‘ฃ๐‘Ž๐‘ŸโŸฉ)
      ; fโŸจ๐‘ŽโŸฉ = ฮป{ {ฯƒ = ฯƒ}{ฯฑ}{t} โ†’ begin
            ๐’œแดฎ.r (๐•ฅ๐•ฃ๐•’๐•ง (๐•’๐•๐•˜ t) ฯƒ) ฯฑ
        โ‰กโŸจ ๐’œแดฎ.rโ‰ˆโ‚ ๐•ฅโŸจ๐•’โŸฉ โŸฉ
            ๐’œแดฎ.r (๐‘Ž๐‘™๐‘” (str ๐’ซแดฎ ๐’œ (โ…€โ‚ ๐•ฅ๐•ฃ๐•’๐•ง t) ฯƒ)) ฯฑ
        โ‰กโŸจ cong (ฮป - โ†’ - ฯฑ) ๐’œrแตƒ.โŸจ๐‘Ž๐‘™๐‘”โŸฉ โŸฉ
            ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (โ…€.Fโ‚ ๐’œแดฎ.r (str ๐’ซแดฎ ๐’œ (โ…€.Fโ‚ ๐•ฅ๐•ฃ๐•’๐•ง t) ฯƒ)) ฯฑ)
        โ‰กห˜โŸจ congr (str-natโ‚‚ ๐’œแดฎ.r (โ…€.Fโ‚ ๐•ฅ๐•ฃ๐•’๐•ง t) ฯƒ) (ฮป - โ†’ ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ - ฯฑ)) โŸฉ
            ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (str ๐’ซแดฎ (โ–ก ๐’œ) (โ…€.Fโ‚ (ฮป { h ฯ‚ โ†’ ๐’œแดฎ.r (h ฯ‚) }) (โ…€.Fโ‚ ๐•ฅ๐•ฃ๐•’๐•ง t)) ฯƒ) ฯฑ)
        โ‰กห˜โŸจ congr โ…€.homomorphism (ฮป - โ†’ ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (str ๐’ซแดฎ (โ–ก ๐’œ) - ฯƒ)  ฯฑ)) โŸฉ
            ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (str ๐’ซแดฎ (โ–ก ๐’œ) (โ…€โ‚ (ฮป{ t ฯƒ โ†’ ๐’œแดฎ.r (๐•ฅ๐•ฃ๐•’๐•ง t ฯƒ)}) t) ฯƒ)  ฯฑ)
        โˆŽ }
      ; gโŸจ๐‘ฃโŸฉ = trans ๐•ฅโŸจ๐•งโŸฉ ฯ†แดฎ.โŸจrโŸฉ
      ; gโŸจ๐‘šโŸฉ = ๐•ฅโŸจ๐•žโŸฉ
      ; gโŸจ๐‘ŽโŸฉ = ฮป{ {ฯƒ = ฯƒ}{ฯฑ}{t} โ†’ begin
            ๐•ฅ๐•ฃ๐•’๐•ง (๐•’๐•๐•˜ t) (ฮป x โ†’ r (ฯƒ x) ฯฑ)
        โ‰กโŸจ ๐•ฅโŸจ๐•’โŸฉ โŸฉ
            ๐‘Ž๐‘™๐‘” (str ๐’ซแดฎ ๐’œ (โ…€โ‚ ๐•ฅ๐•ฃ๐•’๐•ง t) (ฮป x โ†’ r (ฯƒ x) ฯฑ))
        โ‰กโŸจ cong ๐‘Ž๐‘™๐‘” (str-dist ๐’œ (rแถœ ๐’ซแดฎ) (โ…€โ‚ ๐•ฅ๐•ฃ๐•’๐•ง t) ฯƒ ฯฑ) โŸฉ
            ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (str ๐’ซแดฎ (โ–ก ๐’œ) (โ…€.Fโ‚ (precomp ๐’œ r) (โ…€โ‚ ๐•ฅ๐•ฃ๐•’๐•ง t)) ฯƒ) ฯฑ)
        โ‰กห˜โŸจ congr โ…€.homomorphism (ฮป - โ†’ ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ (str ๐’ซแดฎ (โ–ก ๐’œ) - ฯƒ) ฯฑ)) โŸฉ
            ๐‘Ž๐‘™๐‘” (str โ„แดฎ ๐’œ  (str ๐’ซแดฎ (โ–ก ๐’œ) (โ…€โ‚ (ฮป{ t ฯƒ ฯฑ โ†’ ๐•ฅ๐•ฃ๐•’๐•ง t (ฮป v โ†’ r (ฯƒ v) ฯฑ)}) t) ฯƒ) ฯฑ)
        โˆŽ }
      } where open โ‰ก-Reasoning

    -- The traversal map ๐•‹ โ‡พ ใ€–๐’ซ, ๐’œใ€— is pointed coalgebraic if ๐’œ has coalgebra structure
    ๐•ฅ๐•ฃ๐•’๐•งแถœ : Coalgebraic ๐•‹แดฎ ๐’ซแดฎ ๐’œแดฎ ๐•ฅ๐•ฃ๐•’๐•ง
    ๐•ฅ๐•ฃ๐•’๐•งแถœ = record { rโˆ˜f = ฮป{ {ฯƒ = ฯƒ}{ฯฑ}{t = t} โ†’ MapEqโ‚‚.โ‰ˆ rโˆ˜๐•ฅ๐•ฃ๐•’๐•ง t }
                  ; fโˆ˜r = ฮป{ {ฯ = ฯ}{ฯ‚}{t = t} โ†’ cong (ฮป - โ†’ - ฯ‚) (Coalgโ‡’.โŸจrโŸฉ ๐•ฅ๐•ฃ๐•’๐•งแต‡โ‡’ {ฯ = ฯ}{t = t}) }
                  ; fโˆ˜ฮท = trans ๐•ฅโŸจ๐•งโŸฉ ฯ†แดฎ.โŸจฮทโŸฉ }