open import Level
open import Function

open import Data.Unit
open import Data.Product

open import Chapter2.Logic

open import Chapter5.IDesc
open import Chapter5.IDesc.Fixpoint
open import Chapter5.IDesc.Lifting


module Chapter5.IDesc.Induction
          { k : Level}
          {I : Set k}
          (D : func  I I)
          (P : {i : I}  μ D i  Set (k  ))
       where

DAlg : Set (k  )
DAlg = {i : I}{xs :  D ⟧func (μ D) i}  
       [ D ]^ P (i , xs)  P  xs 

module Induction (α : DAlg) where

  mutual
    induction : {i : I}(x : μ D i)  P x
    induction  xs  = α (hyps (func.out D _) xs)
  
    hyps : (D' : IDesc  I)(xs :  D'  (μ D))  [ D' ]^h P xs
    hyps `1 (lift tt) = (lift tt)
    hyps (`var i) xs = induction xs
    hyps (T  T') (t , t') = hyps T t , hyps T' t'
    hyps ( n T) (k , xs) = hyps (T k) xs
    hyps ( S T) (s , xs) = hyps (T s) xs
    hyps ( S T) f = λ s  hyps (T s) (f s)

induction : DAlg  {i : I}(x : μ D i)  P x
induction = Induction.induction