{-# OPTIONS --safe --with-K #-}
open import Prelude
module Generics.Ornament.Algebraic where
open import Prelude.List as List
open import Generics.Telescope
open import Generics.Description
open import Generics.Algebra
open import Generics.Recursion
open import Generics.Ornament
open import Generics.Ornament.Description
private variable
rb : RecB
cb : ConB
cbs : ConBs
algODʳ : {I : Set ℓⁱ} (D : RecD I rb)
{X : I → Set ℓ} (xs : ⟦ D ⟧ʳ X) → RecOD (Σ[ i ∈ I ] X i × ⊤) fst D
algODʳ (ι i ) x = ι (_ , x , tt)
algODʳ (π A D) xs = π λ a → algODʳ (D a) (xs a)
algConB : Level → ConB → ConB
algConB ℓ [] = []
algConB ℓ (inl ℓ' ∷ cb) = inl ℓ' ∷ algConB ℓ cb
algConB ℓ (inr rb ∷ cb) = inl (max-ℓ rb ⊔ ℓ) ∷ inr rb ∷ algConB ℓ cb
algODᶜ : {I : Set ℓⁱ} (D : ConD I cb) {X : I → Set ℓ}
→ Algᶜ D X → ConOD (Σ[ i ∈ I ] X i × ⊤) fst D (algConB ℓ cb)
algODᶜ (ι i ) f = ι (_ , f refl , tt)
algODᶜ (σ A D) f = σ λ a → algODᶜ (D a) λ xs → f (a , xs)
algODᶜ (ρ D E) f = Δ (⟦ D ⟧ʳ _) λ xs →
ρ (algODʳ D xs) (algODᶜ E (λ xs' → f (xs , xs')))
algODᶜˢ : {I : Set ℓⁱ} (D : ConDs I cbs) {X : I → Set ℓ}
→ Algᶜˢ D X → ConODs (Σ[ i ∈ I ] X i × ⊤) fst D (List.map (algConB ℓ) cbs)
algODᶜˢ [] f = []
algODᶜˢ (D ∷ Ds) f = algODᶜ D (f ∘ inl) ∷ ∺ algODᶜˢ Ds (f ∘ inr)
module _ (ℓ : Level) where
algConB-lemma₀ : ∀ cb → max-π (algConB ℓ cb) ≡ max-π cb
algConB-lemma₀ [] = refl
algConB-lemma₀ (inl ℓ' ∷ cb) = algConB-lemma₀ cb
algConB-lemma₀ (inr rb ∷ cb) = cong (max-ℓ rb ⊔_) (algConB-lemma₀ cb)
algConB-lemma₁ : ∀ cbs → maxMap max-π (List.map (algConB ℓ) cbs) ≡ maxMap max-π cbs
algConB-lemma₁ [] = refl
algConB-lemma₁ (cb ∷ cbs) = cong₂ _⊔_ (algConB-lemma₀ cb) (algConB-lemma₁ cbs)
algConB-lemma₂ : ∀ cb → max-σ (algConB ℓ cb) ≡ max-π cb ⊔ max-σ cb ⊔ hasRec? ℓ cb
algConB-lemma₂ [] = refl
algConB-lemma₂ (inl ℓ' ∷ cb) = cong (ℓ' ⊔_) (algConB-lemma₂ cb)
algConB-lemma₂ (inr rb ∷ cb) = cong (ℓ ⊔ max-ℓ rb ⊔_) (algConB-lemma₂ cb)
algConB-lemma₃ : ∀ cbs → maxMap max-σ (List.map (algConB ℓ) cbs)
≡ maxMap max-π cbs ⊔ maxMap max-σ cbs ⊔ maxMap (hasRec? ℓ) cbs
algConB-lemma₃ [] = refl
algConB-lemma₃ (cb ∷ cbs) = cong₂ _⊔_ (algConB-lemma₂ cb) (algConB-lemma₃ cbs)
algOD-level-inequality :
(ℓᵈ : Level) (cbs : ConBs)
→ maxMap max-π cbs ⊔ maxMap max-σ cbs ⊔ ℓᵈ ≡ ℓᵈ
→ maxMap max-π (List.map (algConB ℓ) cbs) ⊔
maxMap max-σ (List.map (algConB ℓ) cbs) ⊔ ℓᵈ ⊔ ℓ ≡ ℓᵈ ⊔ ℓ
algOD-level-inequality ℓᵈ cbs ineq =
begin
maxMap max-π (List.map (algConB ℓ) cbs) ⊔
maxMap max-σ (List.map (algConB ℓ) cbs) ⊔ ℓᵈ ⊔ ℓ
≡⟨ cong (ℓᵈ ⊔ ℓ ⊔_) (cong₂ _⊔_ (algConB-lemma₁ cbs) (algConB-lemma₃ cbs)) ⟩
maxMap max-π cbs ⊔ maxMap max-σ cbs ⊔ maxMap (hasRec? ℓ) cbs ⊔ ℓᵈ ⊔ ℓ
≡⟨ cong (maxMap max-π cbs ⊔ maxMap max-σ cbs ⊔ ℓᵈ ⊔_)
(maxMap-bound (hasRec? ℓ) (hasRec?-bound ℓ) cbs) ⟩
maxMap max-π cbs ⊔ maxMap max-σ cbs ⊔ ℓᵈ ⊔ ℓ
≡⟨ cong (ℓ ⊔_) ineq ⟩
ℓᵈ ⊔ ℓ
∎ where open ≡-Reasoning
AlgOD : (P : FoldP) → DataOD (FoldP.Desc P)
DataOD.#levels (AlgOD P) = FoldP.#levels P
DataOD.level (AlgOD P) = FoldP.level P
DataOD.applyL (AlgOD P) ℓs = AlgODᵖᵈ where
open FoldP P
Dᵖ = DataD.applyL Desc (level ℓs)
AlgODᵖᵈ : PDataOD Dᵖ
PDataOD.alevel AlgODᵖᵈ = PDataD.alevel (DataD.applyL Desc (level ℓs))
PDataOD.plevel AlgODᵖᵈ = _
PDataOD.ilevel AlgODᵖᵈ = _
PDataOD.struct AlgODᵖᵈ = _
PDataOD.level-inequality AlgODᵖᵈ = algOD-level-inequality
(clevel ℓs) (PDataD.dlevel Dᵖ) (PDataD.struct Dᵖ) (PDataD.level-inequality Dᵖ)
PDataOD.Param AlgODᵖᵈ = FoldP.Param P ℓs
PDataOD.param AlgODᵖᵈ = FoldP.param P
PDataOD.Index AlgODᵖᵈ ps = PDataD.Index Dᵖ (param ps) ++ λ is →
Carrier ℓs ps is ∷ λ _ → []
PDataOD.index AlgODᵖᵈ _ = fst
PDataOD.applyP AlgODᵖᵈ ps = algODᶜˢ (PDataD.applyP Dᵖ (param ps)) (algebra ps)
rememberʳ :
{I : Set ℓⁱ} (D : RecD I rb) {X : I → Set ℓˣ}
{N : I → Set ℓ} (fold : ∀ {i} → N i → X i) {N' : Σ[ i ∈ I ] X i × ⊤ → Set ℓ'}
→ (ns : ⟦ D ⟧ʳ N) → Allʳ D (λ i' n → N' (i' , fold n , tt)) ns
→ ⟦ ⌊ algODʳ D (fmapʳ D fold ns) ⌋ʳ ⟧ʳ N'
rememberʳ (ι i ) fold ns n' = n'
rememberʳ (π A D) fold ns all = λ a → rememberʳ (D a) fold (ns a) (all a)
rememberᶜ :
{I : Set ℓⁱ} (D : ConD I cb) {X : I → Set ℓˣ} (f : Algᶜ D X)
{N : I → Set ℓ} (fold : ∀ {i} → N i → X i) {N' : Σ[ i ∈ I ] X i × ⊤ → Set ℓ'}
→ ∀ {i} (ns : ⟦ D ⟧ᶜ N i) → Allᶜ D (λ i' n → N' (i' , fold n , tt)) ns ℓ''
→ ⟦ ⌊ algODᶜ D f ⌋ᶜ ⟧ᶜ N' (i , f (fmapᶜ D fold ns) , tt)
rememberᶜ (ι i ) f fold refl all = refl
rememberᶜ (σ A D) f fold (a , ns ) all = a , rememberᶜ (D a) (curry f a) fold ns all
rememberᶜ (ρ D E) f fold (ns , ns') (all , all') =
fmapʳ D fold ns , rememberʳ D fold ns all , rememberᶜ E (curry f _) fold ns' all'
rememberᶜˢ :
{I : Set ℓⁱ} (D : ConDs I cbs) {X : I → Set ℓˣ} (f : Algᶜˢ D X)
{N : I → Set ℓ} (fold : ∀ {i} → N i → X i) {N' : Σ[ i ∈ I ] X i × ⊤ → Set ℓ'}
→ ∀ {i} (ns : ⟦ D ⟧ᶜˢ N i) → Allᶜˢ D (λ i' n → N' (i' , fold n , tt)) ns ℓ''
→ ⟦ ⌊ algODᶜˢ D f ⌋ᶜˢ ⟧ᶜˢ N' (i , f (fmapᶜˢ D fold ns) , tt)
rememberᶜˢ (D ∷ Ds) f fold (inl ns) all = inl (rememberᶜ D (f ∘ inl) fold ns all)
rememberᶜˢ (D ∷ Ds) f fold (inr ns) all = inr (rememberᶜˢ Ds (f ∘ inr) fold ns all)
remember : ∀ (n : Name) {P f} ⦃ _ : FoldC P f ⦄
{N'} ⦃ _ : Named n (DataC ⌊ AlgOD P ⌋ᵈ N') ⦄ → IndP
remember _ {P} {f} ⦃ C ⦄ {N'} ⦃ named C' ⦄ = let open FoldP P in record
{ Conv = Conv
; #levels = #levels
; level = level
; Param = Param
; param = param
; ParamV = constTelInfo hidden
; ParamN = ParamN
; Carrier = λ ℓs ps is n → N' ℓs ps (is , f ℓs ps n , tt)
; algebra = λ ps ns all → DataC.toN C'
(subst (λ x → ⟦ ⌊ AlgOD P ⌋ᵈ ⟧ᵈ (N' _ ps) (_ , x , tt))
(sym (FoldC.equation C ns))
(rememberᶜˢ (PDataD.applyP (DataD.applyL Desc _) (param ps))
(algebra ps) (f _ ps) ns all)) }