aivika-5.1: Simulation/Aivika/Channel.hs
-- |
-- Module : Simulation.Aivika.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.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.Simulation
import Simulation.Aivika.Dynamics
import Simulation.Aivika.Event
import Simulation.Aivika.Signal
import Simulation.Aivika.Composite
-- | It allows representing a signal transformation.
newtype Channel a b =
Channel { runChannel :: Signal a -> Composite (Signal b)
-- ^ Run the channel transform.
}
instance C.Category Channel where
id = Channel return
(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 :: Double -- ^ the delay
-> Channel a a -- ^ the delay channel
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 :: Event Double -- ^ the delay
-> Channel a a -- ^ the delay channel
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 :: Signal a -> Composite ()
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 :: String -> Channel a b -> Channel a b
traceChannel message (Channel f) =
Channel $ \a ->
do b <- f a
return $
traceSignal message b