packages feed

rhine-0.9: src/FRP/Rhine/ResamplingBuffer/Timeless.hs

{-# LANGUAGE RecordWildCards #-}

{- |
Resampling buffers from asynchronous Mealy machines.
These are used in many other modules implementing 'ResamplingBuffer's.
-}
module FRP.Rhine.ResamplingBuffer.Timeless where

import FRP.Rhine.ResamplingBuffer

{- | An asynchronous, effectful Mealy machine description.
   (Input and output do not happen simultaneously.)
   It can be used to create 'ResamplingBuffer's.
-}
{- FOURMOLU_DISABLE -}
data AsyncMealy m s a b = AsyncMealy
  { amPut :: s -> a -> m     s
  -- ^ Given the previous state and an input value, return the new state.
  , amGet :: s      -> m (b, s)
  -- ^ Given the previous state, return an output value and a new state.
  }
{- FOURMOLU_ENABLE -}

{- | A resampling buffer that is unaware of the time information of the clock,
   and thus clock-polymorphic.
   It is built from an asynchronous Mealy machine description.
   Whenever 'get' is called on @timelessResamplingBuffer machine s@,
   the method 'amGet' is called on @machine@ with state @s@,
   discarding the time stamp. Analogously for 'put'.
-}
timelessResamplingBuffer ::
  Monad m =>
  AsyncMealy m s a b -> -- The asynchronous Mealy machine from which the buffer is built

  -- | The initial state
  s ->
  ResamplingBuffer m cl1 cl2 a b
timelessResamplingBuffer AsyncMealy {..} = go
  where
    go s =
      let
        put _ a = go <$> amPut s a
        get _ = do
          (b, s') <- amGet s
          return (b, go s')
       in
        ResamplingBuffer {..}

-- | A resampling buffer that only accepts and emits units.
trivialResamplingBuffer :: Monad m => ResamplingBuffer m cl1 cl2 () ()
trivialResamplingBuffer =
  timelessResamplingBuffer
    AsyncMealy
      { amPut = const (const (return ()))
      , amGet = const (return ((), ()))
      }
    ()