module Polynomial.InitialPleasingAgda where
open import Function
open import Data.Product
open import Data.Unit
open import Level
open import Prelude.Fam
open import Polynomial.IR
module _ {D : Set1}{c : IR D D} where
mutual
Node' : Poly D -> Set
Node' idPN = U
Node' (con A) = A
Node' (sigma S T) = Σ[ s ∈ Node' S ] Node' (T (info' S s))
Node' (pi A T) = (x : A) -> Node' (T x)
info' : (T : Poly D) -> Node' T -> Info T
info' idPN x = T x
info' (con A) a = lift a
info' (sigma S T) (s , x) = info' S s , info' (T (info' S s)) x
info' (pi A T) g = λ a → info' (T a) (g a)
data U : Set where
intro : Node' (proj₁ c) -> U
T : U -> D
T (intro x) = (proj₂ c) (info' (proj₁ c) x)
module _ {D : Set1}{c : IR D D} where
IH : ∀ {a}(c' : Poly D) ->
(P : U {c = c} -> Set a) -> Node' {c = c} c' -> Set a
IH idPN P x = P x
IH (con A) P a = Lift ⊤
IH (sigma S T) P (x , y) = (IH S P x) × IH (T (info' S x)) P y
IH (pi A T) P f = (a : A) -> IH (T a) P (f a)
mutual
elim : ∀ {a}(P : U {c = c} -> Set a) ->
(step : (x : Node' (proj₁ c)) -> IH (proj₁ c) P x -> P (intro x)) ->
(x : U) -> P x
elim P step (intro x) = step x (mapIH (proj₁ c) P step x)
mapIH : ∀ {a}(c' : Poly D) ->
(P : U {c = c} -> Set a) ->
(step : (x : Node' (proj₁ c)) -> IH (proj₁ c) P x -> P (intro x)) ->
(x : Node' {c = c} c') -> IH c' P x
mapIH idPN P step x = elim P step x
mapIH (con A) P step a = lift tt
mapIH (sigma S T) P step (x , y) = mapIH S P step x , mapIH (T _) P step y
mapIH (pi A T) P step f = λ a → mapIH (T a) P step (f a)