module Polynomial.Monad where

open import Prelude.Basic
open import Prelude.Equality
open import Prelude.Fam
open import Prelude.Equivalences

open import Polynomial.IR

-- unit

IR-η : {D E : Set₁} -> E -> IR D E
IR-η e = con  ,  _  e)

η-equal : {D E : Set₁} -> {Z : Fam D}{e : E} ->  IR-η e  Z  Fam-η e
η-equal = refl

-- multiplication

Poly-μ : {D E : Set1} -> (c : Poly D) -> (α : Info c -> IR D E) ->
          Poly D
Poly-μ c α = sigma c (proj₁  α)

Info-μ : {D E : Set1} -> (c : Poly D) -> (α : Info c -> IR D E) ->
         Info (Poly-μ c α) -> E
Info-μ c α (x , y) = proj₂ (α x) y

IR-μ : {D E : Set1} -> IR D (IR D E) -> IR D E
IR-μ (c , α) = (Poly-μ c α , Info-μ c α)

μ-equal : {D E : Set₁} -> {Z : Fam D}{c : IR D (IR D E)} ->
           IR-μ c  Z  Fam-μ (Fam-map  x   x  Z) ( c  Z))
μ-equal = refl

-- bind

_Polynomial->>=_ : {D E E' : Set₁}  IR D E  (E  IR D E')  IR D E'
c Polynomial->>= h = IR-μ (IR-map h c)

_Polynomial->>=d_ : {C D : Set₁}{E : D -> Set₁} ->
               IR C D  ((d : D)  IR C (E d))  IR C (Σ D E)
c Polynomial->>=d h = IR-μ (IR-map  d  IR-map  e  d , e) (h d)) c)

-- c Polynomial->>=d h = c Polynomial->>= (λ x → IR-map (λ e → (x , e)) (h x))