-- | -- 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