{- |
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
import Data.Stream
import Data.Stream.Optimized (toStreamT)
import Data.Stream.Result (mapResultState)

-- rhine
import FRP.Rhine.ClSF.Core
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 :: forall (m :: Type -> Type) cl2 cl1 a b.
Monad m =>
ClSF m cl2 [(TimeInfo cl1, a)] b -> ResamplingBuffer m cl1 cl2 a b
clsfBuffer = StreamT (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
-> ResamplingBuffer m cl1 cl2 a b
forall (m :: Type -> Type) cl1 a cl2 b.
Monad m =>
StreamT (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
-> ResamplingBuffer m cl1 cl2 a b
clsfBuffer' (StreamT (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
 -> ResamplingBuffer m cl1 cl2 a b)
-> (ClSF m cl2 [(TimeInfo cl1, a)] b
    -> StreamT
         (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b)
-> ClSF m cl2 [(TimeInfo cl1, a)] b
-> ResamplingBuffer m cl1 cl2 a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OptimizedStreamT
  (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
-> StreamT
     (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT (OptimizedStreamT
   (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
 -> StreamT
      (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b)
-> (ClSF m cl2 [(TimeInfo cl1, a)] b
    -> OptimizedStreamT
         (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b)
-> ClSF m cl2 [(TimeInfo cl1, a)] b
-> StreamT
     (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClSF m cl2 [(TimeInfo cl1, a)] b
-> OptimizedStreamT
     (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
forall (m :: Type -> Type) a b.
Automaton m a b -> OptimizedStreamT (ReaderT a m) b
getAutomaton
  where
    clsfBuffer' ::
      (Monad m) =>
      StreamT (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b ->
      ResamplingBuffer m cl1 cl2 a b
    clsfBuffer' :: forall (m :: Type -> Type) cl1 a cl2 b.
Monad m =>
StreamT (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m)) b
-> ResamplingBuffer m cl1 cl2 a b
clsfBuffer' StreamT {s
state :: s
state :: ()
state, s
-> ReaderT
     [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m) (Result s b)
step :: s
-> ReaderT
     [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m) (Result s b)
step :: ()
step} =
      ResamplingBuffer
        { buffer :: (s, [(TimeInfo cl1, a)])
buffer = (s
state, [])
        , put :: TimeInfo cl1
-> a -> (s, [(TimeInfo cl1, a)]) -> m (s, [(TimeInfo cl1, a)])
put = \TimeInfo cl1
ti1 a
a (s
s, [(TimeInfo cl1, a)]
as) -> (s, [(TimeInfo cl1, a)]) -> m (s, [(TimeInfo cl1, a)])
forall a. a -> m a
forall (m :: Type -> Type) a. Monad m => a -> m a
return (s
s, (TimeInfo cl1
ti1, a
a) (TimeInfo cl1, a) -> [(TimeInfo cl1, a)] -> [(TimeInfo cl1, a)]
forall a. a -> [a] -> [a]
: [(TimeInfo cl1, a)]
as)
        , get :: TimeInfo cl2
-> (s, [(TimeInfo cl1, a)])
-> m (Result (s, [(TimeInfo cl1, a)]) b)
get = \TimeInfo cl2
ti2 (s
s, [(TimeInfo cl1, a)]
as) -> (s -> (s, [(TimeInfo cl1, a)]))
-> Result s b -> Result (s, [(TimeInfo cl1, a)]) b
forall s1 s2 a. (s1 -> s2) -> Result s1 a -> Result s2 a
mapResultState (,[]) (Result s b -> Result (s, [(TimeInfo cl1, a)]) b)
-> m (Result s b) -> m (Result (s, [(TimeInfo cl1, a)]) b)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT (TimeInfo cl2) m (Result s b)
-> TimeInfo cl2 -> m (Result s b)
forall r (m :: Type -> Type) a. ReaderT r m a -> r -> m a
runReaderT (ReaderT [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m) (Result s b)
-> [(TimeInfo cl1, a)] -> ReaderT (TimeInfo cl2) m (Result s b)
forall r (m :: Type -> Type) a. ReaderT r m a -> r -> m a
runReaderT (s
-> ReaderT
     [(TimeInfo cl1, a)] (ReaderT (TimeInfo cl2) m) (Result s b)
step s
s) [(TimeInfo cl1, a)]
as) TimeInfo cl2
ti2
        }