module Chapter6.IDesc.FreeMonad.Examples.IDesc where

open import Level 
  hiding (zero)
  renaming (suc to sucL)

open import Data.Unit
open import Data.Nat hiding (_*_ ; _⊔_)
open import Data.Fin hiding (lift)
open import Data.Vec hiding (_>>=_)
open import Data.Product
open import Data.String

open import Chapter2.Logic

open import Chapter5.IDesc
open import Chapter5.IDesc.Tagged
open import Chapter5.IDesc.Fixpoint

open import Chapter6.IDesc.FreeMonad
open import Chapter6.IDesc.FreeMonad.IMonad
open import Chapter6.IDesc.FreeMonad.Monad

IDescD : ( : Level){k : Level}  tagDesc (k  (sucL )) 
IDescD  {k} = (5 ,  _  
            `1  
            `var tt  `var tt  `1  
            ( (Lift ) λ { (lift n)  ( (Lift (Fin n)) λ _  `var tt)  `1 }) 
            ( (Lift {sucL }{k} (Set )) λ { (lift S)  ( (Lift {sucL }{k} (Lift {}{sucL } S)) λ _  `var tt)  `1 } )  
            ( (Lift {sucL }{k} (Set )) λ { (lift S)  ( (Lift {sucL }{k} (Lift {}{sucL } S)) λ _  `var tt)  `1 })  [])) ,
            _  0) , λ _  []

IDesc' : ∀( : Level){k}  Set k  Set (k  (sucL ))
IDesc'  {k} I = (IDescD  {k} *  _  Lift {k}{sucL } I)) tt

record func' ( : Level){k : Level}(I J : Set k) : Set (k  sucL ) where
  constructor mk
  field
    out : J  IDesc'  I


`var' : ∀{ k}{I : Set k}  I  IDesc'  I
`var' {} i = `v {D = IDescD } (lift i)

`1' : ∀{ k}{I : Set k}  IDesc'  I
`1' =  lift (suc zero) , lift tt 

_`×'_ : ∀{ k}{I : Set k} (A B : IDesc'  I)  IDesc'   I
A `×' B =  lift (suc (suc zero)) , A , B , lift tt 

`σ' : ∀{ k}{I : Set k} (n : )(T : Fin n  IDesc'  I)  IDesc'  I
`σ' n T =  lift (suc (suc (suc zero))) , lift n ,  { (lift k)  T k }) , lift tt 

`Σ' : ∀{ k}{I : Set k} (S : Set )(T : S  IDesc'  I)  IDesc'  I
`Σ' S T =  lift (suc (suc (suc (suc zero)))) , lift S ,  { (lift (lift s))  T s }) , lift tt 

`Π' : ∀{ k}{I : Set k} (S : Set )(T : S  IDesc'  I)  IDesc'  I
`Π' S T =  lift (suc (suc (suc (suc (suc zero))))) , lift S ,  { (lift (lift s))  T s }) , lift tt 


_∘_ : ∀{ k}{I J K : Set k}  func'  J K  func'  I J  func'  I K
_∘_ {} D E = func'.mk  k  func'.out D k >>=  { (lift j)  func'.out E j }))
  where open RawIMonad (monad (IDescD ))