open import Data.Unit
open import Data.Product

open import Chapter1.Logic

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


module Chapter2.IDesc.Lifting
          {I : Set}
          {X : I  Set} where


[_]^h : (D : IDesc I)(P : ∀{i}  X i  Set) (xs :  D  X)  Set
[ `1 ]^h P tt = 
[ `var i ]^h P xs = P xs
[ T  T' ]^h P (t , t') =  [ T ]^h P t × [ T' ]^h P t'
[  n T ]^h P (k , xs) = [ T k ]^h P xs
[  S T ]^h P (s , xs) = [ T s ]^h P xs
[  S T ]^h P f = (s : S)  [ T s ]^h P (f s) 

[_]^hmap : (D : IDesc I){P : ∀{i}  X i  Set}(p : ∀{i}  (x : X i)  P x)
          (xs :  D  X)  [ D ]^h P xs
[ `1 ]^hmap p tt = tt
[ `var i ]^hmap p xs = p xs
[ T  T' ]^hmap p (t , t')= [ T ]^hmap p t , [ T' ]^hmap p t'
[  n T ]^hmap p (k , xs) = [ T k ]^hmap p xs
[  S T ]^hmap p (s , xs) = [ T s ]^hmap p xs
[  S T ]^hmap p f = λ s  [ T s ]^hmap p (f s)

[_]^ : (D : func I I)(P : ∀{i}  X i  Set)(xs : Σ[ i  I ]  D ⟧func X i)  Set
[ D ]^ P (i , xs) = [ func.out D i ]^h P xs

[_]^map : (D : func I I){P : ∀{i}  X i  Set}(p : ∀{i}  (x : X i)  P x)
          (xs : Σ[ i  I ]  D ⟧func X i)  [ D ]^ P xs
[ D ]^map p (i , xs) = [ func.out D i ]^hmap p xs 


-- Intellectual curiosity:

[_]^hD : (D : IDesc I)(xs :  D  X)  IDesc (Σ I X)
[ `1 ]^hD tt = `1
[ `var i ]^hD xs = `var (i , xs)
[ T  T' ]^hD (t , t') =  [ T ]^hD t  [ T' ]^hD t'
[  n T ]^hD (k , xs) = [ T k ]^hD xs
[  S T ]^hD (s , xs) = [ T s ]^hD xs
[  S T ]^hD f =  S λ s  [ T s ]^hD (f s) 

[_]^hmapD : (D : IDesc I){P : Σ I X  Set}(p : ∀{i}  (x : X i)  P (i , x)) 
           (xs :  D  X)   ([ D ]^hD xs)   _  )   [ D ]^hD xs  P
[ D ]^hmapD p xs =  [ D ]^hD xs ⟧map  {ix} tt  p (proj₂ ix))