module Chapter5.Equivalence.ToContainer 
         {I J : Set}
       where

open import Level 
  renaming ( zero to zeroL 
           ; suc to sucL )

open import Data.Empty
open import Data.Unit
open import Data.Sum
open import Data.Nat
open import Data.Fin
open import Data.Product

open import Chapter5.IDesc
open import Chapter5.Container


Shape : IDesc zeroL I  Set
Shape `1 = 
Shape (`var i) = 
Shape (D₁  D₂) = Shape D₁ × Shape D₂
Shape ( n T) = Σ[ k  Fin n ] Shape (T k)
Shape ( S T) = Σ[ s  S ] Shape (T s)
Shape ( S T) = (s : S)  Shape (T s)
  
Pos : (D : IDesc zeroL I)  Shape D  Set
Pos `1 tt = 
Pos (`var i) sh = 
Pos (D₁  D₂) (d₁ , d₂) = Pos D₁ d₁  Pos D₂ d₂
Pos ( n T) (k , t) = Pos (T k) t
Pos ( S T) (s , t) = Pos (T s) t
Pos ( S T) f = Σ[ s  S ]  Pos (T s) (f s)

Next : (D : IDesc zeroL I)(sh : Shape D)  Pos D sh  I
Next `1 sh ()
Next (`var j) tt tt = j
Next (D₁  D₂) (d₁ , d₂) (inj₁ p₁) = Next D₁ d₁ p₁
Next (D₁  D₂) (d₁ , d₂) (inj₂ p₂) = Next D₂ d₂ p₂
Next ( n T) (k , sh) ps = Next (T k) sh ps
Next ( S T) (s , sh) ps = Next (T s) sh ps
Next ( S T) f (s , ps) = Next (T s) (f s) ps

⟨_⟩ : func zeroL I J  I  J
 D  = record { S = λ j  Shape (func.out D j)
               ; P = λ {j} sh  Pos (func.out D j) sh
               ; n = λ {j}{sh} ps  Next (func.out D j) sh ps }