open import Data.Unit
open import Data.Product

open import Chapter1.Logic

open import Chapter2.IDesc
open import Chapter2.IDesc.Fixpoint

module Chapter2.IDesc.InitialAlgebra
          {I : Set}
          (D : func I I) where

Alg : (I  Set)  Set
Alg X =  D ⟧func X  X

module Fold  {X : I  Set}(α : Alg X)
       where

  mutual
    fold : {i : I}  μ D i  X i
    fold  xs  = α (hyps (func.out D _) xs)

    hyps : (D' : IDesc I)  
           (xs :  D'  (μ D)) 
            D'  X
    hyps `1 tt = tt
    hyps (`var i) xs = fold xs
    hyps (T  T') (t , t') = hyps T t , hyps T' t'
    hyps ( n T) (k , xs) = k , hyps (T k) xs
    hyps ( S T) (s , xs) = s , hyps (T s) xs
    hyps ( S T) f = λ s  hyps (T s) (f s)

fold : {X : I  Set}(α : Alg X) 
        μ D  X
fold = Fold.fold