module Filter.MonadFix where

import qualified Filter.Graph as Graph
import qualified Filter.Fix   as FFix

import Filter.Fix (Channel(Channel), ChannelId)

import Control.Monad.State (StateT, evalStateT, get, modify, lift)
import Control.Monad.Writer (Writer, execWriter, tell)


{-|
If you find 'Filter.Fix.T' still inconvenient,
and if you don't care about portability,
you can also use the following monad with the @mdo@ notation.

> mdo
>   v <- a(u + dw)
>   w <- b(v + ey)
>   y <- c w

-}


type T filter t a v x  =  StateT ChannelId (Writer [Channel filter t a v]) x

makeChannel ::
   [(ChannelId, filter t a v)] ->
   T filter t a v ChannelId
makeChannel inputs =
   do n <- get
      modify succ
      lift $ tell [Channel n inputs]
      return n


run :: T filter t a v x -> [Channel filter t a v]
run m = execWriter (evalStateT m 0)


toGraph :: T filter t a v x -> Graph.T filter Int t a v
toGraph =
   Graph.fromList . map (\(Channel n inputs) -> (n, inputs)) . run