module FRP.Rhine.SyncSF where
import Control.Arrow
import Control.Category (Category)
import qualified Control.Category (id)
import Control.Monad.Trans.Reader
(ReaderT, ask, asks, mapReaderT, withReaderT)
import Data.MonadicStreamFunction
(MSF, liftMSFPurer, liftMSFTrans, arrM, arrM_, sumFrom, delay, feedback)
import Data.VectorSpace
import FRP.Rhine.Clock
import FRP.Rhine.TimeDomain
type SyncSF m cl a b = MSF (ReaderT (TimeInfo cl) m) a b
type SyncSignal m cl a = SyncSF m cl () a
type Behaviour m td a = forall cl. td ~ TimeDomainOf cl => SyncSignal m cl a
type Behavior m td a = Behaviour m td a
hoistSyncSF
:: (Monad m1, Monad m2)
=> (forall c. m1 c -> m2 c)
-> SyncSF m1 cl a b
-> SyncSF m2 (HoistClock m1 m2 cl) a b
hoistSyncSF hoist = liftMSFPurer $ withReaderT (retag id) . mapReaderT hoist
timeless :: Monad m => MSF m a b -> SyncSF m cl a b
timeless = liftMSFTrans
arrMSync :: Monad m => (a -> m b) -> SyncSF m cl a b
arrMSync = timeless . arrM
arrMSync_ :: Monad m => m b -> SyncSF m cl a b
arrMSync_ = timeless . arrM_
timeInfo :: Monad m => SyncSF m cl a (TimeInfo cl)
timeInfo = arrM_ ask
timeInfoOf :: Monad m => (TimeInfo cl -> b) -> SyncSF m cl a b
timeInfoOf f = arrM_ $ asks f
infixr 6 >->
(>->) :: Category cat
=> cat a b
-> cat b c
-> cat a c
(>->) = (>>>)
infixl 6 <-<
(<-<) :: Category cat
=> cat b c
-> cat a b
-> cat a c
(<-<) = (<<<)
arr_ :: Arrow a => b -> a c b
arr_ = arr . const
syncId :: Monad m => SyncSF m cl a a
syncId = Control.Category.id
integralFrom
:: ( Monad m, VectorSpace v
, Groundfield v ~ Diff (TimeDomainOf cl))
=> v -> SyncSF m cl v v
integralFrom v0 = proc v -> do
_sinceTick <- timeInfoOf sinceTick -< ()
sumFrom v0 -< _sinceTick *^ v
integral
:: ( Monad m, VectorSpace v
, Groundfield v ~ Diff (TimeDomainOf cl))
=> SyncSF m cl v v
integral = integralFrom zeroVector
derivativeFrom
:: ( Monad m, VectorSpace v
, Groundfield v ~ Diff (TimeDomainOf cl))
=> v -> SyncSF m cl v v
derivativeFrom v0 = proc v -> do
vLast <- delay v0 -< v
TimeInfo {..} <- timeInfo -< ()
returnA -< (v ^-^ vLast) ^/ sinceTick
derivative
:: ( Monad m, VectorSpace v
, Groundfield v ~ Diff (TimeDomainOf cl))
=> SyncSF m cl v v
derivative = derivativeFrom zeroVector
weightedAverageFrom
:: ( Monad m, VectorSpace v
, Groundfield v ~ Diff (TimeDomainOf cl))
=> v
-> SyncSF m cl (v, Groundfield v) v
weightedAverageFrom v0 = feedback v0 $ proc ((v, weight), vAvg) -> do
let
vAvg' = weight *^ vAvg ^+^ (1 weight) *^ v
returnA -< (vAvg', vAvg')
averageFrom
:: ( Monad m, VectorSpace v
, Floating (Groundfield v)
, Groundfield v ~ Diff (TimeDomainOf cl))
=> v
-> Diff (TimeDomainOf cl)
-> SyncSF m cl v v
averageFrom v0 t = proc v -> do
TimeInfo {..} <- timeInfo -< ()
let
weight = exp $ (sinceTick / t)
weightedAverageFrom v0 -< (v, weight)
average
:: ( Monad m, VectorSpace v
, Floating (Groundfield v)
, Groundfield v ~ Diff (TimeDomainOf cl))
=> Diff (TimeDomainOf cl)
-> SyncSF m cl v v
average = averageFrom zeroVector
averageLinFrom
:: ( Monad m, VectorSpace v
, Groundfield v ~ Diff (TimeDomainOf cl))
=> v
-> Diff (TimeDomainOf cl)
-> SyncSF m cl v v
averageLinFrom v0 t = proc v -> do
TimeInfo {..} <- timeInfo -< ()
let
weight = t / (sinceTick + t)
weightedAverageFrom v0 -< (v, weight)
averageLin
:: ( Monad m, VectorSpace v
, Groundfield v ~ Diff (TimeDomainOf cl))
=> Diff (TimeDomainOf cl)
-> SyncSF m cl v v
averageLin = averageLinFrom zeroVector