packages feed

rhine-1.7: src/FRP/Rhine/ResamplingBuffer/ClSF.hs

{- |
Collect and process all incoming values statefully and with time stamps.
-}
module FRP.Rhine.ResamplingBuffer.ClSF where

-- transformers
import Control.Monad.Trans.Reader (ReaderT, runReaderT)

-- automaton
import Data.Automaton hiding (toStreamT)
import Data.Stream
import Data.Stream.Optimized (toStreamT)
import Data.Stream.Result (mapResultState)

-- rhine
import FRP.Rhine.ClSF.Core hiding (toStreamT)
import FRP.Rhine.ResamplingBuffer

{- | Given a clocked signal function that accepts
   a varying number of timestamped inputs (a list),
   a `ResamplingBuffer` can be formed
   that collects all this input and steps the signal function
   whenever output is requested.
-}
clsfBuffer ::
  (Monad m) =>
  {- | The clocked signal function that consumes
  and a list of timestamped inputs,
  and outputs a single value.
  The list will contain the /newest/ element in the head.
  -}
  ClSF m cl2 [(TimeInfo cl1, a)] b ->
  ResamplingBuffer m cl1 cl2 a b
clsfBuffer = clsfBuffer' . toStreamT . getAutomaton
  where
    clsfBuffer' ::
      (Monad m) =>
      StreamT (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b ->
      ResamplingBuffer m cl1 cl2 a b
    clsfBuffer' StreamT {state, step} =
      ResamplingBuffer
        { buffer = (state, [])
        , put = \ti1 a (s, as) -> pure (s, (ti1, a) : as)
        , get = \ti2 (s, as) -> mapResultState (,[]) <$> runReaderT (runReaderT (step s) as) ti2
        }