{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, FlexibleInstances, UndecidableInstances, RecursiveDo, MonoLocalBinds #-}
module Simulation.Aivika.Trans.Composite
(
Composite,
CompositeLift(..),
runComposite,
runComposite_,
runCompositeInStartTime_,
runCompositeInStopTime_,
disposableComposite) where
import Data.Monoid
import Control.Exception
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Fix
import Control.Monad.Fail
import Control.Applicative
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.DES
import Simulation.Aivika.Trans.Parameter
import Simulation.Aivika.Trans.Simulation
import Simulation.Aivika.Trans.Dynamics
import Simulation.Aivika.Trans.Event
newtype Composite m a = Composite { runComposite :: DisposableEvent m -> Event m (a, DisposableEvent m)
}
runComposite_ :: Monad m => Composite m a -> Event m a
{-# INLINABLE runComposite_ #-}
runComposite_ m =
do (a, _) <- runComposite m mempty
return a
runCompositeInStartTime_ :: MonadDES m => Composite m a -> Simulation m a
{-# INLINABLE runCompositeInStartTime_ #-}
runCompositeInStartTime_ = runEventInStartTime . runComposite_
runCompositeInStopTime_ :: MonadDES m => Composite m a -> Simulation m a
{-# INLINABLE runCompositeInStopTime_ #-}
runCompositeInStopTime_ = runEventInStopTime . runComposite_
disposableComposite :: Monad m => DisposableEvent m -> Composite m ()
{-# INLINABLE disposableComposite #-}
disposableComposite h = Composite $ \h0 -> return ((), h0 <> h)
instance Monad m => Functor (Composite m) where
{-# INLINE fmap #-}
fmap f (Composite m) =
Composite $ \h0 ->
do (a, h) <- m h0
return (f a, h)
instance Monad m => Applicative (Composite m) where
{-# INLINE pure #-}
pure = return
{-# INLINE (<*>) #-}
(<*>) = ap
instance Monad m => Monad (Composite m) where
{-# INLINE return #-}
return a = Composite $ \h0 -> return (a, h0)
{-# INLINE (>>=) #-}
(Composite m) >>= k =
Composite $ \h0 ->
do (a, h) <- m h0
let Composite m' = k a
(b, h') <- m' h
return (b, h')
instance Monad m => MonadFail (Composite m) where
{-# INLINE fail #-}
fail = error
instance (Monad m, MonadIO (Event m)) => MonadIO (Composite m) where
{-# INLINE liftIO #-}
liftIO m =
Composite $ \h0 ->
do a <- liftIO m
return (a, h0)
instance (Monad m, MonadFix (Event m)) => MonadFix (Composite m) where
{-# INLINABLE mfix #-}
mfix f =
Composite $ \h0 ->
do rec (a, h) <- runComposite (f a) h0
return (a, h)
instance MonadTrans Composite where
{-# INLINE lift #-}
lift m =
Composite $ \h0 ->
do a <- lift m
return (a, h0)
instance Monad m => MonadCompTrans Composite m where
{-# INLINE liftComp #-}
liftComp m =
Composite $ \h0 ->
do a <- liftComp m
return (a, h0)
instance Monad m => ParameterLift Composite m where
{-# INLINE liftParameter #-}
liftParameter m =
Composite $ \h0 ->
do a <- liftParameter m
return (a, h0)
instance Monad m => SimulationLift Composite m where
{-# INLINE liftSimulation #-}
liftSimulation m =
Composite $ \h0 ->
do a <- liftSimulation m
return (a, h0)
instance Monad m => DynamicsLift Composite m where
{-# INLINE liftDynamics #-}
liftDynamics m =
Composite $ \h0 ->
do a <- liftDynamics m
return (a, h0)
instance Monad m => EventLift Composite m where
{-# INLINE liftEvent #-}
liftEvent m =
Composite $ \h0 ->
do a <- liftEvent m
return (a, h0)
class CompositeLift t m where
liftComposite :: Composite m a -> t m a
instance Monad m => CompositeLift Composite m where
{-# INLINE liftComposite #-}
liftComposite = id