open import Chapter1.Logic

open import Data.Unit
open import Data.Product

open import Chapter2.IDesc
open import Chapter2.IDesc.Fixpoint
open import Chapter2.IDesc.Lifting
open import Chapter2.IDesc.Induction


module Chapter3.IDesc.InitialAlgebra 
         {I : Set}{X : I  Set}
         (D : func I I)
         (α :  D ⟧func X  X)
       where


fold : μ D  X
fold x = induction D  {i} _  X i) 
                    {i}{xs} ih  α (replace (func.out D i) xs ih))
                   x
  where replace : (D' : IDesc I)(xs :  D'  (μ D)) 
                  (ih : [ D' ]^h  {i} _  X i) xs) 
                   D'  X
        replace (`var i) xs x = x
        replace `1 tt tt = tt
        replace (D  D') (xs , xs') (x , x') = replace D xs x , replace D' xs' x'
        replace ( n T) (k , xs) ih = k , replace (T k) xs ih
        replace ( S T) (s , xs) ih = s , replace (T s) xs ih
        replace ( S T) xs ih = λ s  replace (T s) (xs s) (ih s)