aivika-transformers-5.1: Simulation/Aivika/Trans/Channel.hs
-- |
-- 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