{-# OPTIONS --safe --sized-types #-} module StateOfTheArt.CDMM where open import Size open import Data.Empty open import Data.Bool open import Data.Nat using (ℕ ; suc) open import Data.Unit open import Data.Product as Prod open import Function open import Relation.Unary open import Relation.Binary.PropositionalEquality hiding ([_]) data Desc (I J : Set) : Set₁ where `σ : (A : Set) → (A → Desc I J) → Desc I J `X : J → Desc I J → Desc I J `∎ : I → Desc I J private variable I J : Set i : I j : J d : Desc I J X Y : J → Set s : Size A B : Set `K : Set → I → Desc I J `K A i = `σ A (λ _ → `∎ i) infixr 5 _`+_ _`+_ : Desc I J → Desc I J → Desc I J d `+ e = `σ Bool $ λ { true → d ; false → e } ⟦_⟧ : Desc I J → (J → Set) → (I → Set) ⟦ `σ A d ⟧ X i = Σ[ a ∈ A ] (⟦ d a ⟧ X i) ⟦ `X j d ⟧ X i = X j × ⟦ d ⟧ X i ⟦ `∎ i′ ⟧ X i = i ≡ i′ fmap : (d : Desc I J) → ∀[ X ⇒ Y ] → ∀[ ⟦ d ⟧ X ⇒ ⟦ d ⟧ Y ] fmap (`σ A d) f (a , v) = (a , fmap (d a) f v) fmap (`X j d) f (r , v) = (f r , fmap d f v) fmap (`∎ i) f t = t data μ (d : Desc I I) : Size → I → Set where `con : ⟦ d ⟧ (μ d s) i → μ d (↑ s) i fold : (d : Desc I I) → ∀[ ⟦ d ⟧ X ⇒ X ] → ∀[ μ d s ⇒ X ] fold d alg (`con t) = alg (fmap d (fold d alg) t) finD : Desc ℕ ℕ finD = `σ ℕ $ λ index → `σ Bool $ λ isZero → if isZero then `∎ (suc index) else `X index (`∎ (suc index)) fin : ℕ → Set fin = μ finD ∞ fin0-elim : fin 0 → ⊥ fin0-elim (`con (_ , true , ())) fin0-elim (`con (_ , false , _ , ())) fz : ∀ n → fin (suc n) fz n = `con (n , true , refl) fs : ∀ n → fin n → fin (suc n) fs n k = `con (n , false , k , refl) listD : Set → Desc ⊤ ⊤ listD A = `σ Bool $ λ isNil → if isNil then `∎ tt else `σ A (λ _ → `X tt (`∎ tt)) List : Set → Set List A = μ (listD A) ∞ tt infixr 10 _∷_ pattern []' = (true , refl) pattern [] = `con []' pattern _∷'_ x xs = (false , x , xs , refl) pattern _∷_ x xs = `con (x ∷' xs) example : List (List Bool) example = (false ∷ []) ∷ (true ∷ []) ∷ [] vecD : Set → Desc ℕ ℕ vecD A = `σ Bool $ λ isNil → if isNil then `∎ 0 else `σ ℕ (λ n → `σ A (λ _ → `X n (`∎ (suc n)))) Vec : Set → ℕ → Set Vec A = μ (vecD A) ∞ foldr : (A → B → B) → B → List A → B foldr c n = fold (listD _) $ λ where []' → n (hd ∷' rec) → c hd rec _++_ : List A → List A → List A _++_ = foldr (λ hd rec → hd ∷_ ∘ rec) id flatten : List (List A) → List A flatten = foldr _++_ [] test : flatten example ≡ false ∷ true ∷ [] test = refl