-- | -- Module : Simulation.Aivika.Trans.Channel -- Copyright : Copyright (c) 2009-2017, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental -- Tested with: GHC 8.0.1 -- -- The module defines a channel that transforms one 'Signal' to another -- within the 'Composite' computation. -- module Simulation.Aivika.Trans.Channel (-- * Channel Computation Channel(..), -- * Delay Channel delayChannel, delayChannelM, -- * Sinking Signal sinkSignal, -- * Debugging traceChannel) where import qualified Control.Category as C import Control.Monad import Simulation.Aivika.Trans.DES import Simulation.Aivika.Trans.Simulation import Simulation.Aivika.Trans.Dynamics import Simulation.Aivika.Trans.Event import Simulation.Aivika.Trans.Signal import Simulation.Aivika.Trans.Composite -- | It allows representing a signal transformation. newtype Channel m a b = Channel { runChannel :: Signal m a -> Composite m (Signal m b) -- ^ Run the channel transform. } instance MonadDES m => C.Category (Channel m) where {-# INLINE id #-} id = Channel return {-# INLINE (.) #-} (Channel g) . (Channel f) = Channel $ \a -> f a >>= g -- | Return a delayed signal. -- -- This is actually the 'delaySignal' function wrapped in the 'Channel' type. delayChannel :: MonadDES m => Double -- ^ the delay -> Channel m a a -- ^ the delay channel {-# INLINABLE delayChannel #-} delayChannel delay = Channel $ \a -> return $ delaySignal delay a -- | Like 'delayChannel', but it re-computes the delay each time. -- -- This is actually the 'delaySignalM' function wrapped in the 'Channel' type. delayChannelM :: MonadDES m => Event m Double -- ^ the delay -> Channel m a a -- ^ the delay channel {-# INLINABLE delayChannelM #-} delayChannelM delay = Channel $ \a -> return $ delaySignalM delay a -- | Sink the signal. It returns a computation that subscribes to -- the signal and then ignores the received data. The resulting -- computation can be a moving force to simulate the whole system of -- the interconnected signals and channels. sinkSignal :: MonadDES m => Signal m a -> Composite m () {-# INLINABLE sinkSignal #-} sinkSignal a = do h <- liftEvent $ handleSignal a $ const $ return () disposableComposite h -- | Show the debug message with the current simulation time, -- when emitting the output signal. traceChannel :: MonadDES m => String -> Channel m a b -> Channel m a b {-# INLINABLE traceChannel #-} traceChannel message (Channel f) = Channel $ \a -> do b <- f a return $ traceSignal message b