{-# LANGUAGE RecordWildCards #-}

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

-- dunai
import Data.MonadicStreamFunction.InternalCore

-- rhine
import FRP.Rhine.ResamplingBuffer

{- | Given a monadic stream function that accepts
   a varying number of inputs (a list),
   a `ResamplingBuffer` can be formed
   that collects all input in a timestamped list.
-}
msfBuffer ::
  (Monad m) =>
  -- | The monadic stream function that consumes
  --   a single time stamp for the moment when an output value is required,
  --   and a list of timestamped inputs,
  --   and outputs a single value.
  --   The list will contain the /newest/ element in the head.
  MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b ->
  ResamplingBuffer m cl1 cl2 a b
msfBuffer :: forall (m :: Type -> Type) cl2 cl1 a b.
Monad m =>
MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
-> ResamplingBuffer m cl1 cl2 a b
msfBuffer = forall (m :: Type -> Type) cl1 a cl2 b.
Monad m =>
[(TimeInfo cl1, a)]
-> MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
-> ResamplingBuffer m cl1 cl2 a b
msfBuffer' []
  where
    msfBuffer' ::
      (Monad m) =>
      [(TimeInfo cl1, a)] ->
      MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b ->
      ResamplingBuffer m cl1 cl2 a b
    msfBuffer' :: forall (m :: Type -> Type) cl1 a cl2 b.
Monad m =>
[(TimeInfo cl1, a)]
-> MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
-> ResamplingBuffer m cl1 cl2 a b
msfBuffer' [(TimeInfo cl1, a)]
as MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
msf = ResamplingBuffer {TimeInfo cl1 -> a -> m (ResamplingBuffer m cl1 cl2 a b)
TimeInfo cl2 -> m (b, ResamplingBuffer m cl1 cl2 a b)
get :: TimeInfo cl2 -> m (b, ResamplingBuffer m cl1 cl2 a b)
put :: TimeInfo cl1 -> a -> m (ResamplingBuffer m cl1 cl2 a b)
get :: TimeInfo cl2 -> m (b, ResamplingBuffer m cl1 cl2 a b)
put :: TimeInfo cl1 -> a -> m (ResamplingBuffer m cl1 cl2 a b)
..}
      where
        put :: TimeInfo cl1 -> a -> m (ResamplingBuffer m cl1 cl2 a b)
put TimeInfo cl1
ti1 a
a = forall (m :: Type -> Type) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (m :: Type -> Type) cl1 a cl2 b.
Monad m =>
[(TimeInfo cl1, a)]
-> MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
-> ResamplingBuffer m cl1 cl2 a b
msfBuffer' ((TimeInfo cl1
ti1, a
a) forall a. a -> [a] -> [a]
: [(TimeInfo cl1, a)]
as) MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
msf
        get :: TimeInfo cl2 -> m (b, ResamplingBuffer m cl1 cl2 a b)
get TimeInfo cl2
ti2 = do
          (b
b, MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
msf') <- forall (m :: Type -> Type) a b. MSF m a b -> a -> m (b, MSF m a b)
unMSF MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
msf (TimeInfo cl2
ti2, [(TimeInfo cl1, a)]
as)
          forall (m :: Type -> Type) a. Monad m => a -> m a
return (b
b, forall (m :: Type -> Type) cl2 cl1 a b.
Monad m =>
MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
-> ResamplingBuffer m cl1 cl2 a b
msfBuffer MSF m (TimeInfo cl2, [(TimeInfo cl1, a)]) b
msf')