module Simulation.Aivika.RealTime.Internal.RT
(RT(..),
RTParams(..),
RTContext(..),
RTScaling(..),
invokeRT,
runRT,
defaultRTParams,
newRTContext,
rtParams,
rtChannel,
rtScale) where
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Trans.Exception
import Simulation.Aivika.Trans.Internal.Types
import Simulation.Aivika.RealTime.Internal.Channel
data RTScaling = RTLinearScaling Double
| RTLogScaling Double
| RTScalingFunction (Double -> Double -> Double)
rtScale :: RTScaling
-> Double
-> Double
-> Double
rtScale (RTLinearScaling k) t0 t = k * (t t0)
rtScale (RTLogScaling k) t0 t = k * log (t t0)
rtScale (RTScalingFunction f) t0 t = f t0 t
data RTParams =
RTParams { rtScaling :: RTScaling,
rtIntervalDelta :: Double
}
newtype RT m a = RT { unRT :: RTContext m -> m a
}
data RTContext m =
RTContext { rtChannel0 :: Channel (Event (RT m) ()),
rtParams0 :: RTParams
}
instance Monad m => Monad (RT m) where
return = RT . const . return
(RT m) >>= k = RT $ \ctx ->
m ctx >>= \a ->
let m' = unRT (k a) in m' ctx
instance Applicative m => Applicative (RT m) where
pure = RT . const . pure
(RT f) <*> (RT m) = RT $ \ctx -> f ctx <*> m ctx
instance Functor m => Functor (RT m) where
fmap f (RT m) = RT $ fmap f . m
instance MonadIO m => MonadIO (RT m) where
liftIO = RT . const . liftIO
instance MonadException m => MonadException (RT m) where
catchComp (RT m) h = RT $ \ctx ->
catchComp (m ctx) (\e -> unRT (h e) ctx)
finallyComp (RT m1) (RT m2) = RT $ \ctx ->
finallyComp (m1 ctx) (m2 ctx)
throwComp e = RT $ \ctx ->
throwComp e
invokeRT :: RTContext m -> RT m a -> m a
invokeRT ctx (RT m) = m ctx
defaultRTParams :: RTParams
defaultRTParams =
RTParams { rtScaling = RTLinearScaling 1,
rtIntervalDelta = 0.001
}
rtParams :: Monad m => RT m RTParams
rtParams = RT $ return . rtParams0
rtChannel :: Monad m => RT m (Channel (Event (RT m) ()))
rtChannel = RT $ return . rtChannel0
runRT :: RT m a -> RTContext m -> m a
runRT = unRT
newRTContext :: RTParams -> IO (RTContext m)
newRTContext ps =
do channel <- newChannel
return RTContext { rtChannel0 = channel,
rtParams0 = ps }