{-# LANGUAGE RecursiveDo, Arrows #-}

-- |
-- Module     : Simulation.Aivika.Trans.Circuit
-- 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
--
-- It represents a circuit synchronized with the event queue.
-- Also it allows creating the recursive links with help of
-- the proc-notation.
--
-- The implementation is based on the <http://en.wikibooks.org/wiki/Haskell/Arrow_tutorial Arrow Tutorial>.
--
module Simulation.Aivika.Trans.Circuit
       (-- * The Circuit Arrow
        Circuit(..),
        iterateCircuitInIntegTimes,
        iterateCircuitInIntegTimes_,
        iterateCircuitInIntegTimesMaybe,
        iterateCircuitInIntegTimesEither,
        iterateCircuitInTimes,
        iterateCircuitInTimes_,
        iterateCircuitInTimesMaybe,
        iterateCircuitInTimesEither,
        -- * Circuit Primitives
        arrCircuit,
        accumCircuit,
        -- * The Arrival Circuit
        arrivalCircuit,
        -- * Delaying the Circuit
        delayCircuit,
        -- * The Time Circuit
        timeCircuit,
        -- * Conditional Computation
        (<?<),
        (>?>),
        filterCircuit,
        filterCircuitM,
        neverCircuit,
        -- * Converting to Signals and Processors
        circuitSignaling,
        circuitProcessor,
        -- * Integrals and Difference Equations
        integCircuit,
        integCircuitEither,
        sumCircuit,
        sumCircuitEither,
        -- * The Circuit Transform
        circuitTransform,
        -- * Debugging
        traceCircuit) where

import qualified Control.Category as C
import Control.Arrow
import Control.Monad.Fix

import Simulation.Aivika.Trans.Ref.Base
import Simulation.Aivika.Trans.DES
import Simulation.Aivika.Trans.SD
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Dynamics.Memo
import Simulation.Aivika.Trans.Transform
import Simulation.Aivika.Trans.SystemDynamics
import Simulation.Aivika.Trans.Signal
import Simulation.Aivika.Trans.Stream
import Simulation.Aivika.Trans.Process
import Simulation.Aivika.Trans.Processor
import Simulation.Aivika.Trans.Task
import Simulation.Aivika.Arrival (Arrival(..))

-- | Represents a circuit synchronized with the event queue.
-- Besides, it allows creating the recursive links with help of
-- the proc-notation.
--
newtype Circuit m a b =
  Circuit { forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit :: a -> Event m (b, Circuit m a b)
            -- ^ Run the circuit.
          }

instance MonadDES m => C.Category (Circuit m) where

  {-# INLINABLE id #-}
  id :: forall a. Circuit m a a
id = (a -> Event m (a, Circuit m a a)) -> Circuit m a a
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (a, Circuit m a a)) -> Circuit m a a)
-> (a -> Event m (a, Circuit m a a)) -> Circuit m a a
forall a b. (a -> b) -> a -> b
$ \a
a -> (a, Circuit m a a) -> Event m (a, Circuit m a a)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a, Circuit m a a
forall a. Circuit m a a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
C.id)

  {-# INLINABLE (.) #-}
  . :: forall b c a. Circuit m b c -> Circuit m a b -> Circuit m a c
(.) = Circuit m b c -> Circuit m a b -> Circuit m a c
forall {m :: * -> *} {a} {b} {a}.
Monad m =>
Circuit m a b -> Circuit m a a -> Circuit m a b
dot
    where 
      (Circuit a -> Event m (b, Circuit m a b)
g) dot :: Circuit m a b -> Circuit m a a -> Circuit m a b
`dot` (Circuit a -> Event m (a, Circuit m a a)
f) =
        (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (b, Circuit m a b)) -> Circuit m a b)
-> (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall a b. (a -> b) -> a -> b
$ \a
a ->
        (Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b))
-> (Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
        do (a
b, Circuit m a a
cir1) <- Point m -> Event m (a, Circuit m a a) -> m (a, Circuit m a a)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (a -> Event m (a, Circuit m a a)
f a
a)
           (b
c, Circuit m a b
cir2) <- Point m -> Event m (b, Circuit m a b) -> m (b, Circuit m a b)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (a -> Event m (b, Circuit m a b)
g a
b)
           (b, Circuit m a b) -> m (b, Circuit m a b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
c, Circuit m a b
cir2 Circuit m a b -> Circuit m a a -> Circuit m a b
`dot` Circuit m a a
cir1)

instance MonadDES m => Arrow (Circuit m) where

  {-# INLINABLE arr #-}
  arr :: forall b c. (b -> c) -> Circuit m b c
arr b -> c
f = (b -> Event m (c, Circuit m b c)) -> Circuit m b c
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((b -> Event m (c, Circuit m b c)) -> Circuit m b c)
-> (b -> Event m (c, Circuit m b c)) -> Circuit m b c
forall a b. (a -> b) -> a -> b
$ \b
a -> (c, Circuit m b c) -> Event m (c, Circuit m b c)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> c
f b
a, (b -> c) -> Circuit m b c
forall b c. (b -> c) -> Circuit m b c
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr b -> c
f)

  {-# INLINABLE first #-}
  first :: forall b c d. Circuit m b c -> Circuit m (b, d) (c, d)
first (Circuit b -> Event m (c, Circuit m b c)
f) =
    ((b, d) -> Event m ((c, d), Circuit m (b, d) (c, d)))
-> Circuit m (b, d) (c, d)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit (((b, d) -> Event m ((c, d), Circuit m (b, d) (c, d)))
 -> Circuit m (b, d) (c, d))
-> ((b, d) -> Event m ((c, d), Circuit m (b, d) (c, d)))
-> Circuit m (b, d) (c, d)
forall a b. (a -> b) -> a -> b
$ \(b
b, d
d) ->
    (Point m -> m ((c, d), Circuit m (b, d) (c, d)))
-> Event m ((c, d), Circuit m (b, d) (c, d))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ((c, d), Circuit m (b, d) (c, d)))
 -> Event m ((c, d), Circuit m (b, d) (c, d)))
-> (Point m -> m ((c, d), Circuit m (b, d) (c, d)))
-> Event m ((c, d), Circuit m (b, d) (c, d))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    do (c
c, Circuit m b c
cir) <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c, Circuit m b c)
f b
b)
       ((c, d), Circuit m (b, d) (c, d))
-> m ((c, d), Circuit m (b, d) (c, d))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((c
c, d
d), Circuit m b c -> Circuit m (b, d) (c, d)
forall b c d. Circuit m b c -> Circuit m (b, d) (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first Circuit m b c
cir)

  {-# INLINABLE second #-}
  second :: forall b c d. Circuit m b c -> Circuit m (d, b) (d, c)
second (Circuit b -> Event m (c, Circuit m b c)
f) =
    ((d, b) -> Event m ((d, c), Circuit m (d, b) (d, c)))
-> Circuit m (d, b) (d, c)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit (((d, b) -> Event m ((d, c), Circuit m (d, b) (d, c)))
 -> Circuit m (d, b) (d, c))
-> ((d, b) -> Event m ((d, c), Circuit m (d, b) (d, c)))
-> Circuit m (d, b) (d, c)
forall a b. (a -> b) -> a -> b
$ \(d
d, b
b) ->
    (Point m -> m ((d, c), Circuit m (d, b) (d, c)))
-> Event m ((d, c), Circuit m (d, b) (d, c))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ((d, c), Circuit m (d, b) (d, c)))
 -> Event m ((d, c), Circuit m (d, b) (d, c)))
-> (Point m -> m ((d, c), Circuit m (d, b) (d, c)))
-> Event m ((d, c), Circuit m (d, b) (d, c))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    do (c
c, Circuit m b c
cir) <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c, Circuit m b c)
f b
b)
       ((d, c), Circuit m (d, b) (d, c))
-> m ((d, c), Circuit m (d, b) (d, c))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((d
d, c
c), Circuit m b c -> Circuit m (d, b) (d, c)
forall b c d. Circuit m b c -> Circuit m (d, b) (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second Circuit m b c
cir)

  {-# INLINABLE (***) #-}
  (Circuit b -> Event m (c, Circuit m b c)
f) *** :: forall b c b' c'.
Circuit m b c -> Circuit m b' c' -> Circuit m (b, b') (c, c')
*** (Circuit b' -> Event m (c', Circuit m b' c')
g) =
    ((b, b') -> Event m ((c, c'), Circuit m (b, b') (c, c')))
-> Circuit m (b, b') (c, c')
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit (((b, b') -> Event m ((c, c'), Circuit m (b, b') (c, c')))
 -> Circuit m (b, b') (c, c'))
-> ((b, b') -> Event m ((c, c'), Circuit m (b, b') (c, c')))
-> Circuit m (b, b') (c, c')
forall a b. (a -> b) -> a -> b
$ \(b
b, b'
b') ->
    (Point m -> m ((c, c'), Circuit m (b, b') (c, c')))
-> Event m ((c, c'), Circuit m (b, b') (c, c'))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ((c, c'), Circuit m (b, b') (c, c')))
 -> Event m ((c, c'), Circuit m (b, b') (c, c')))
-> (Point m -> m ((c, c'), Circuit m (b, b') (c, c')))
-> Event m ((c, c'), Circuit m (b, b') (c, c'))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    do (c
c, Circuit m b c
cir1) <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c, Circuit m b c)
f b
b)
       (c'
c', Circuit m b' c'
cir2) <- Point m -> Event m (c', Circuit m b' c') -> m (c', Circuit m b' c')
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b' -> Event m (c', Circuit m b' c')
g b'
b')
       ((c, c'), Circuit m (b, b') (c, c'))
-> m ((c, c'), Circuit m (b, b') (c, c'))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((c
c, c'
c'), Circuit m b c
cir1 Circuit m b c -> Circuit m b' c' -> Circuit m (b, b') (c, c')
forall b c b' c'.
Circuit m b c -> Circuit m b' c' -> Circuit m (b, b') (c, c')
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** Circuit m b' c'
cir2)
       
  {-# INLINABLE (&&&) #-}
  (Circuit b -> Event m (c, Circuit m b c)
f) &&& :: forall b c c'.
Circuit m b c -> Circuit m b c' -> Circuit m b (c, c')
&&& (Circuit b -> Event m (c', Circuit m b c')
g) =
    (b -> Event m ((c, c'), Circuit m b (c, c')))
-> Circuit m b (c, c')
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((b -> Event m ((c, c'), Circuit m b (c, c')))
 -> Circuit m b (c, c'))
-> (b -> Event m ((c, c'), Circuit m b (c, c')))
-> Circuit m b (c, c')
forall a b. (a -> b) -> a -> b
$ \b
b ->
    (Point m -> m ((c, c'), Circuit m b (c, c')))
-> Event m ((c, c'), Circuit m b (c, c'))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ((c, c'), Circuit m b (c, c')))
 -> Event m ((c, c'), Circuit m b (c, c')))
-> (Point m -> m ((c, c'), Circuit m b (c, c')))
-> Event m ((c, c'), Circuit m b (c, c'))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    do (c
c, Circuit m b c
cir1) <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c, Circuit m b c)
f b
b)
       (c'
c', Circuit m b c'
cir2) <- Point m -> Event m (c', Circuit m b c') -> m (c', Circuit m b c')
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c', Circuit m b c')
g b
b)
       ((c, c'), Circuit m b (c, c')) -> m ((c, c'), Circuit m b (c, c'))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((c
c, c'
c'), Circuit m b c
cir1 Circuit m b c -> Circuit m b c' -> Circuit m b (c, c')
forall b c c'.
Circuit m b c -> Circuit m b c' -> Circuit m b (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& Circuit m b c'
cir2)

instance (MonadDES m, MonadFix m) => ArrowLoop (Circuit m) where

  {-# INLINABLE loop #-}
  loop :: forall b d c. Circuit m (b, d) (c, d) -> Circuit m b c
loop (Circuit (b, d) -> Event m ((c, d), Circuit m (b, d) (c, d))
f) =
    (b -> Event m (c, Circuit m b c)) -> Circuit m b c
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((b -> Event m (c, Circuit m b c)) -> Circuit m b c)
-> (b -> Event m (c, Circuit m b c)) -> Circuit m b c
forall a b. (a -> b) -> a -> b
$ \b
b ->
    (Point m -> m (c, Circuit m b c)) -> Event m (c, Circuit m b c)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (c, Circuit m b c)) -> Event m (c, Circuit m b c))
-> (Point m -> m (c, Circuit m b c)) -> Event m (c, Circuit m b c)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    do rec ((c
c, d
d), Circuit m (b, d) (c, d)
cir) <- Point m
-> Event m ((c, d), Circuit m (b, d) (c, d))
-> m ((c, d), Circuit m (b, d) (c, d))
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p ((b, d) -> Event m ((c, d), Circuit m (b, d) (c, d))
f (b
b, d
d))
       (c, Circuit m b c) -> m (c, Circuit m b c)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (c
c, Circuit m (b, d) (c, d) -> Circuit m b c
forall b d c. Circuit m (b, d) (c, d) -> Circuit m b c
forall (a :: * -> * -> *) b d c.
ArrowLoop a =>
a (b, d) (c, d) -> a b c
loop Circuit m (b, d) (c, d)
cir)

instance MonadDES m => ArrowChoice (Circuit m) where

  {-# INLINABLE left #-}
  left :: forall b c d. Circuit m b c -> Circuit m (Either b d) (Either c d)
left x :: Circuit m b c
x@(Circuit b -> Event m (c, Circuit m b c)
f) =
    (Either b d
 -> Event m (Either c d, Circuit m (Either b d) (Either c d)))
-> Circuit m (Either b d) (Either c d)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either b d
  -> Event m (Either c d, Circuit m (Either b d) (Either c d)))
 -> Circuit m (Either b d) (Either c d))
-> (Either b d
    -> Event m (Either c d, Circuit m (Either b d) (Either c d)))
-> Circuit m (Either b d) (Either c d)
forall a b. (a -> b) -> a -> b
$ \Either b d
ebd ->
    (Point m -> m (Either c d, Circuit m (Either b d) (Either c d)))
-> Event m (Either c d, Circuit m (Either b d) (Either c d))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Either c d, Circuit m (Either b d) (Either c d)))
 -> Event m (Either c d, Circuit m (Either b d) (Either c d)))
-> (Point m -> m (Either c d, Circuit m (Either b d) (Either c d)))
-> Event m (Either c d, Circuit m (Either b d) (Either c d))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    case Either b d
ebd of
      Left b
b ->
        do (c
c, Circuit m b c
cir) <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c, Circuit m b c)
f b
b)
           (Either c d, Circuit m (Either b d) (Either c d))
-> m (Either c d, Circuit m (Either b d) (Either c d))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (c -> Either c d
forall a b. a -> Either a b
Left c
c, Circuit m b c -> Circuit m (Either b d) (Either c d)
forall b c d. Circuit m b c -> Circuit m (Either b d) (Either c d)
forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either b d) (Either c d)
left Circuit m b c
cir)
      Right d
d ->
        (Either c d, Circuit m (Either b d) (Either c d))
-> m (Either c d, Circuit m (Either b d) (Either c d))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (d -> Either c d
forall a b. b -> Either a b
Right d
d, Circuit m b c -> Circuit m (Either b d) (Either c d)
forall b c d. Circuit m b c -> Circuit m (Either b d) (Either c d)
forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either b d) (Either c d)
left Circuit m b c
x)

  {-# INLINABLE right #-}
  right :: forall b c d. Circuit m b c -> Circuit m (Either d b) (Either d c)
right x :: Circuit m b c
x@(Circuit b -> Event m (c, Circuit m b c)
f) =
    (Either d b
 -> Event m (Either d c, Circuit m (Either d b) (Either d c)))
-> Circuit m (Either d b) (Either d c)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either d b
  -> Event m (Either d c, Circuit m (Either d b) (Either d c)))
 -> Circuit m (Either d b) (Either d c))
-> (Either d b
    -> Event m (Either d c, Circuit m (Either d b) (Either d c)))
-> Circuit m (Either d b) (Either d c)
forall a b. (a -> b) -> a -> b
$ \Either d b
edb ->
    (Point m -> m (Either d c, Circuit m (Either d b) (Either d c)))
-> Event m (Either d c, Circuit m (Either d b) (Either d c))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Either d c, Circuit m (Either d b) (Either d c)))
 -> Event m (Either d c, Circuit m (Either d b) (Either d c)))
-> (Point m -> m (Either d c, Circuit m (Either d b) (Either d c)))
-> Event m (Either d c, Circuit m (Either d b) (Either d c))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    case Either d b
edb of
      Right b
b ->
        do (c
c, Circuit m b c
cir) <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c, Circuit m b c)
f b
b)
           (Either d c, Circuit m (Either d b) (Either d c))
-> m (Either d c, Circuit m (Either d b) (Either d c))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (c -> Either d c
forall a b. b -> Either a b
Right c
c, Circuit m b c -> Circuit m (Either d b) (Either d c)
forall b c d. Circuit m b c -> Circuit m (Either d b) (Either d c)
forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right Circuit m b c
cir)
      Left d
d ->
        (Either d c, Circuit m (Either d b) (Either d c))
-> m (Either d c, Circuit m (Either d b) (Either d c))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (d -> Either d c
forall a b. a -> Either a b
Left d
d, Circuit m b c -> Circuit m (Either d b) (Either d c)
forall b c d. Circuit m b c -> Circuit m (Either d b) (Either d c)
forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either d b) (Either d c)
right Circuit m b c
x)

  {-# INLINABLE (+++) #-}
  x :: Circuit m b c
x@(Circuit b -> Event m (c, Circuit m b c)
f) +++ :: forall b c b' c'.
Circuit m b c
-> Circuit m b' c' -> Circuit m (Either b b') (Either c c')
+++ y :: Circuit m b' c'
y@(Circuit b' -> Event m (c', Circuit m b' c')
g) =
    (Either b b'
 -> Event m (Either c c', Circuit m (Either b b') (Either c c')))
-> Circuit m (Either b b') (Either c c')
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either b b'
  -> Event m (Either c c', Circuit m (Either b b') (Either c c')))
 -> Circuit m (Either b b') (Either c c'))
-> (Either b b'
    -> Event m (Either c c', Circuit m (Either b b') (Either c c')))
-> Circuit m (Either b b') (Either c c')
forall a b. (a -> b) -> a -> b
$ \Either b b'
ebb' ->
    (Point m -> m (Either c c', Circuit m (Either b b') (Either c c')))
-> Event m (Either c c', Circuit m (Either b b') (Either c c'))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m
  -> m (Either c c', Circuit m (Either b b') (Either c c')))
 -> Event m (Either c c', Circuit m (Either b b') (Either c c')))
-> (Point m
    -> m (Either c c', Circuit m (Either b b') (Either c c')))
-> Event m (Either c c', Circuit m (Either b b') (Either c c'))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    case Either b b'
ebb' of
      Left b
b ->
        do (c
c, Circuit m b c
cir1) <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (c, Circuit m b c)
f b
b)
           (Either c c', Circuit m (Either b b') (Either c c'))
-> m (Either c c', Circuit m (Either b b') (Either c c'))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (c -> Either c c'
forall a b. a -> Either a b
Left c
c, Circuit m b c
cir1 Circuit m b c
-> Circuit m b' c' -> Circuit m (Either b b') (Either c c')
forall b c b' c'.
Circuit m b c
-> Circuit m b' c' -> Circuit m (Either b b') (Either c c')
forall (a :: * -> * -> *) b c b' c'.
ArrowChoice a =>
a b c -> a b' c' -> a (Either b b') (Either c c')
+++ Circuit m b' c'
y)
      Right b'
b' ->
        do (c'
c', Circuit m b' c'
cir2) <- Point m -> Event m (c', Circuit m b' c') -> m (c', Circuit m b' c')
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b' -> Event m (c', Circuit m b' c')
g b'
b')
           (Either c c', Circuit m (Either b b') (Either c c'))
-> m (Either c c', Circuit m (Either b b') (Either c c'))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (c' -> Either c c'
forall a b. b -> Either a b
Right c'
c', Circuit m b c
x Circuit m b c
-> Circuit m b' c' -> Circuit m (Either b b') (Either c c')
forall b c b' c'.
Circuit m b c
-> Circuit m b' c' -> Circuit m (Either b b') (Either c c')
forall (a :: * -> * -> *) b c b' c'.
ArrowChoice a =>
a b c -> a b' c' -> a (Either b b') (Either c c')
+++ Circuit m b' c'
cir2)

  {-# INLINABLE (|||) #-}
  x :: Circuit m b d
x@(Circuit b -> Event m (d, Circuit m b d)
f) ||| :: forall b d c.
Circuit m b d -> Circuit m c d -> Circuit m (Either b c) d
||| y :: Circuit m c d
y@(Circuit c -> Event m (d, Circuit m c d)
g) =
    (Either b c -> Event m (d, Circuit m (Either b c) d))
-> Circuit m (Either b c) d
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either b c -> Event m (d, Circuit m (Either b c) d))
 -> Circuit m (Either b c) d)
-> (Either b c -> Event m (d, Circuit m (Either b c) d))
-> Circuit m (Either b c) d
forall a b. (a -> b) -> a -> b
$ \Either b c
ebc ->
    (Point m -> m (d, Circuit m (Either b c) d))
-> Event m (d, Circuit m (Either b c) d)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (d, Circuit m (Either b c) d))
 -> Event m (d, Circuit m (Either b c) d))
-> (Point m -> m (d, Circuit m (Either b c) d))
-> Event m (d, Circuit m (Either b c) d)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
    case Either b c
ebc of
      Left b
b ->
        do (d
d, Circuit m b d
cir1) <- Point m -> Event m (d, Circuit m b d) -> m (d, Circuit m b d)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m (d, Circuit m b d)
f b
b)
           (d, Circuit m (Either b c) d) -> m (d, Circuit m (Either b c) d)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (d
d, Circuit m b d
cir1 Circuit m b d -> Circuit m c d -> Circuit m (Either b c) d
forall b d c.
Circuit m b d -> Circuit m c d -> Circuit m (Either b c) d
forall (a :: * -> * -> *) b d c.
ArrowChoice a =>
a b d -> a c d -> a (Either b c) d
||| Circuit m c d
y)
      Right c
b' ->
        do (d
d, Circuit m c d
cir2) <- Point m -> Event m (d, Circuit m c d) -> m (d, Circuit m c d)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (c -> Event m (d, Circuit m c d)
g c
b')
           (d, Circuit m (Either b c) d) -> m (d, Circuit m (Either b c) d)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (d
d, Circuit m b d
x Circuit m b d -> Circuit m c d -> Circuit m (Either b c) d
forall b d c.
Circuit m b d -> Circuit m c d -> Circuit m (Either b c) d
forall (a :: * -> * -> *) b d c.
ArrowChoice a =>
a b d -> a c d -> a (Either b c) d
||| Circuit m c d
cir2)

-- | Get a signal transform by the specified circuit.
circuitSignaling :: MonadDES m => Circuit m a b -> Signal m a -> Signal m b
{-# INLINABLE circuitSignaling #-}
circuitSignaling :: forall (m :: * -> *) a b.
MonadDES m =>
Circuit m a b -> Signal m a -> Signal m b
circuitSignaling (Circuit a -> Event m (b, Circuit m a b)
cir) Signal m a
sa =
  Signal { handleSignal :: (b -> Event m ()) -> Event m (DisposableEvent m)
handleSignal = \b -> Event m ()
f ->
            do Ref m (a -> Event m (b, Circuit m a b))
r <- Simulation m (Ref m (a -> Event m (b, Circuit m a b)))
-> Event m (Ref m (a -> Event m (b, Circuit m a b)))
forall a. Simulation m a -> Event m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
SimulationLift t m =>
Simulation m a -> t m a
liftSimulation (Simulation m (Ref m (a -> Event m (b, Circuit m a b)))
 -> Event m (Ref m (a -> Event m (b, Circuit m a b))))
-> Simulation m (Ref m (a -> Event m (b, Circuit m a b)))
-> Event m (Ref m (a -> Event m (b, Circuit m a b)))
forall a b. (a -> b) -> a -> b
$ (a -> Event m (b, Circuit m a b))
-> Simulation m (Ref m (a -> Event m (b, Circuit m a b)))
forall a. a -> Simulation m (Ref m a)
forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef a -> Event m (b, Circuit m a b)
cir
               Signal m a -> (a -> Event m ()) -> Event m (DisposableEvent m)
forall (m :: * -> *) a.
Signal m a -> (a -> Event m ()) -> Event m (DisposableEvent m)
handleSignal Signal m a
sa ((a -> Event m ()) -> Event m (DisposableEvent m))
-> (a -> Event m ()) -> Event m (DisposableEvent m)
forall a b. (a -> b) -> a -> b
$ \a
a ->
                 (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
                 do a -> Event m (b, Circuit m a b)
cir <- Point m
-> Event m (a -> Event m (b, Circuit m a b))
-> m (a -> Event m (b, Circuit m a b))
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (a -> Event m (b, Circuit m a b))
 -> m (a -> Event m (b, Circuit m a b)))
-> Event m (a -> Event m (b, Circuit m a b))
-> m (a -> Event m (b, Circuit m a b))
forall a b. (a -> b) -> a -> b
$ Ref m (a -> Event m (b, Circuit m a b))
-> Event m (a -> Event m (b, Circuit m a b))
forall a. Ref m a -> Event m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef Ref m (a -> Event m (b, Circuit m a b))
r
                    (b
b, Circuit a -> Event m (b, Circuit m a b)
cir') <- Point m -> Event m (b, Circuit m a b) -> m (b, Circuit m a b)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (a -> Event m (b, Circuit m a b)
cir a
a)
                    Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ Ref m (a -> Event m (b, Circuit m a b))
-> (a -> Event m (b, Circuit m a b)) -> Event m ()
forall a. Ref m a -> a -> Event m ()
forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef Ref m (a -> Event m (b, Circuit m a b))
r a -> Event m (b, Circuit m a b)
cir'
                    Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (b -> Event m ()
f b
b) }

-- | Transform the circuit to a processor.
circuitProcessor :: MonadDES m => Circuit m a b -> Processor m a b
{-# INLINABLE circuitProcessor #-}
circuitProcessor :: forall (m :: * -> *) a b.
MonadDES m =>
Circuit m a b -> Processor m a b
circuitProcessor (Circuit a -> Event m (b, Circuit m a b)
cir) = (Stream m a -> Stream m b) -> Processor m a b
forall (m :: * -> *) a b.
(Stream m a -> Stream m b) -> Processor m a b
Processor ((Stream m a -> Stream m b) -> Processor m a b)
-> (Stream m a -> Stream m b) -> Processor m a b
forall a b. (a -> b) -> a -> b
$ \Stream m a
sa ->
  Process m (b, Stream m b) -> Stream m b
forall (m :: * -> *) a. Process m (a, Stream m a) -> Stream m a
Cons (Process m (b, Stream m b) -> Stream m b)
-> Process m (b, Stream m b) -> Stream m b
forall a b. (a -> b) -> a -> b
$
  do (a
a, Stream m a
xs) <- Stream m a -> Process m (a, Stream m a)
forall (m :: * -> *) a. Stream m a -> Process m (a, Stream m a)
runStream Stream m a
sa
     (b
b, Circuit m a b
cir') <- Event m (b, Circuit m a b) -> Process m (b, Circuit m a b)
forall a. Event m a -> Process m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
EventLift t m =>
Event m a -> t m a
liftEvent (a -> Event m (b, Circuit m a b)
cir a
a)
     let f :: Stream m a -> Stream m b
f = Processor m a b -> Stream m a -> Stream m b
forall (m :: * -> *) a b.
Processor m a b -> Stream m a -> Stream m b
runProcessor (Circuit m a b -> Processor m a b
forall (m :: * -> *) a b.
MonadDES m =>
Circuit m a b -> Processor m a b
circuitProcessor Circuit m a b
cir')
     (b, Stream m b) -> Process m (b, Stream m b)
forall a. a -> Process m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, Stream m a -> Stream m b
f Stream m a
xs)

-- | Create a simple circuit by the specified handling function
-- that runs the computation for each input value to get an output.
arrCircuit :: MonadDES m => (a -> Event m b) -> Circuit m a b
{-# INLINABLE arrCircuit #-}
arrCircuit :: forall (m :: * -> *) a b.
MonadDES m =>
(a -> Event m b) -> Circuit m a b
arrCircuit a -> Event m b
f =
  let x :: Circuit m a b
x =
        (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (b, Circuit m a b)) -> Circuit m a b)
-> (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall a b. (a -> b) -> a -> b
$ \a
a ->
        (Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b))
-> (Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
        do b
b <- Point m -> Event m b -> m b
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (a -> Event m b
f a
a)
           (b, Circuit m a b) -> m (b, Circuit m a b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, Circuit m a b
x)
  in Circuit m a b
x

-- | Accumulator that outputs a value determined by the supplied function.
accumCircuit :: MonadDES m => (acc -> a -> Event m (acc, b)) -> acc -> Circuit m a b
{-# INLINABLE accumCircuit #-}
accumCircuit :: forall (m :: * -> *) acc a b.
MonadDES m =>
(acc -> a -> Event m (acc, b)) -> acc -> Circuit m a b
accumCircuit acc -> a -> Event m (acc, b)
f acc
acc =
  (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (b, Circuit m a b)) -> Circuit m a b)
-> (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall a b. (a -> b) -> a -> b
$ \a
a ->
  (Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b))
-> (Point m -> m (b, Circuit m a b)) -> Event m (b, Circuit m a b)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do (acc
acc', b
b) <- Point m -> Event m (acc, b) -> m (acc, b)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (acc -> a -> Event m (acc, b)
f acc
acc a
a)
     (b, Circuit m a b) -> m (b, Circuit m a b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, (acc -> a -> Event m (acc, b)) -> acc -> Circuit m a b
forall (m :: * -> *) acc a b.
MonadDES m =>
(acc -> a -> Event m (acc, b)) -> acc -> Circuit m a b
accumCircuit acc -> a -> Event m (acc, b)
f acc
acc') 

-- | A circuit that adds the information about the time points at which 
-- the values were received.
arrivalCircuit :: MonadDES m => Circuit m a (Arrival a)
{-# INLINABLE arrivalCircuit #-}
arrivalCircuit :: forall (m :: * -> *) a. MonadDES m => Circuit m a (Arrival a)
arrivalCircuit =
  let loop :: Maybe Double -> Circuit m a (Arrival a)
loop Maybe Double
t0 =
        (a -> Event m (Arrival a, Circuit m a (Arrival a)))
-> Circuit m a (Arrival a)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (Arrival a, Circuit m a (Arrival a)))
 -> Circuit m a (Arrival a))
-> (a -> Event m (Arrival a, Circuit m a (Arrival a)))
-> Circuit m a (Arrival a)
forall a b. (a -> b) -> a -> b
$ \a
a ->
        (Point m -> m (Arrival a, Circuit m a (Arrival a)))
-> Event m (Arrival a, Circuit m a (Arrival a))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Arrival a, Circuit m a (Arrival a)))
 -> Event m (Arrival a, Circuit m a (Arrival a)))
-> (Point m -> m (Arrival a, Circuit m a (Arrival a)))
-> Event m (Arrival a, Circuit m a (Arrival a))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
        let t :: Double
t = Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p
            b :: Arrival a
b = Arrival { arrivalValue :: a
arrivalValue = a
a,
                          arrivalTime :: Double
arrivalTime  = Double
t,
                          arrivalDelay :: Maybe Double
arrivalDelay = 
                            case Maybe Double
t0 of
                              Maybe Double
Nothing -> Maybe Double
forall a. Maybe a
Nothing
                              Just Double
t0 -> Double -> Maybe Double
forall a. a -> Maybe a
Just (Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
t0) }
        in (Arrival a, Circuit m a (Arrival a))
-> m (Arrival a, Circuit m a (Arrival a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Arrival a
b, Maybe Double -> Circuit m a (Arrival a)
loop (Maybe Double -> Circuit m a (Arrival a))
-> Maybe Double -> Circuit m a (Arrival a)
forall a b. (a -> b) -> a -> b
$ Double -> Maybe Double
forall a. a -> Maybe a
Just Double
t)
  in Maybe Double -> Circuit m a (Arrival a)
forall {m :: * -> *} {a}.
Monad m =>
Maybe Double -> Circuit m a (Arrival a)
loop Maybe Double
forall a. Maybe a
Nothing

-- | Delay the input by one step using the specified initial value.
delayCircuit :: MonadDES m => a -> Circuit m a a
{-# INLINABLE delayCircuit #-}
delayCircuit :: forall (m :: * -> *) a. MonadDES m => a -> Circuit m a a
delayCircuit a
a0 =
  (a -> Event m (a, Circuit m a a)) -> Circuit m a a
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (a, Circuit m a a)) -> Circuit m a a)
-> (a -> Event m (a, Circuit m a a)) -> Circuit m a a
forall a b. (a -> b) -> a -> b
$ \a
a ->
  (a, Circuit m a a) -> Event m (a, Circuit m a a)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a0, a -> Circuit m a a
forall (m :: * -> *) a. MonadDES m => a -> Circuit m a a
delayCircuit a
a)

-- | A circuit that returns the current modeling time.
timeCircuit :: MonadDES m => Circuit m a Double
{-# INLINABLE timeCircuit #-}
timeCircuit :: forall (m :: * -> *) a. MonadDES m => Circuit m a Double
timeCircuit =
  (a -> Event m (Double, Circuit m a Double)) -> Circuit m a Double
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (Double, Circuit m a Double)) -> Circuit m a Double)
-> (a -> Event m (Double, Circuit m a Double))
-> Circuit m a Double
forall a b. (a -> b) -> a -> b
$ \a
a ->
  (Point m -> m (Double, Circuit m a Double))
-> Event m (Double, Circuit m a Double)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Double, Circuit m a Double))
 -> Event m (Double, Circuit m a Double))
-> (Point m -> m (Double, Circuit m a Double))
-> Event m (Double, Circuit m a Double)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  (Double, Circuit m a Double) -> m (Double, Circuit m a Double)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p, Circuit m a Double
forall (m :: * -> *) a. MonadDES m => Circuit m a Double
timeCircuit)

-- | Like '>>>' but processes only the represented events.
(>?>) :: MonadDES m
         => Circuit m a (Maybe b)
         -- ^ whether there is an event
         -> Circuit m b c
         -- ^ process the event if it presents
         -> Circuit m a (Maybe c)
         -- ^ the resulting circuit that processes only the represented events
{-# INLINABLE (>?>) #-}
Circuit m a (Maybe b)
whether >?> :: forall (m :: * -> *) a b c.
MonadDES m =>
Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c)
>?> Circuit m b c
process =
  (a -> Event m (Maybe c, Circuit m a (Maybe c)))
-> Circuit m a (Maybe c)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (Maybe c, Circuit m a (Maybe c)))
 -> Circuit m a (Maybe c))
-> (a -> Event m (Maybe c, Circuit m a (Maybe c)))
-> Circuit m a (Maybe c)
forall a b. (a -> b) -> a -> b
$ \a
a ->
  (Point m -> m (Maybe c, Circuit m a (Maybe c)))
-> Event m (Maybe c, Circuit m a (Maybe c))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Maybe c, Circuit m a (Maybe c)))
 -> Event m (Maybe c, Circuit m a (Maybe c)))
-> (Point m -> m (Maybe c, Circuit m a (Maybe c)))
-> Event m (Maybe c, Circuit m a (Maybe c))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do (Maybe b
b, Circuit m a (Maybe b)
whether') <- Point m
-> Event m (Maybe b, Circuit m a (Maybe b))
-> m (Maybe b, Circuit m a (Maybe b))
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Circuit m a (Maybe b)
-> a -> Event m (Maybe b, Circuit m a (Maybe b))
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a (Maybe b)
whether a
a)
     case Maybe b
b of
       Maybe b
Nothing ->
         (Maybe c, Circuit m a (Maybe c))
-> m (Maybe c, Circuit m a (Maybe c))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe c
forall a. Maybe a
Nothing, Circuit m a (Maybe b)
whether' Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c)
forall (m :: * -> *) a b c.
MonadDES m =>
Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c)
>?> Circuit m b c
process)
       Just b
b  ->
         do (c
c, Circuit m b c
process') <- Point m -> Event m (c, Circuit m b c) -> m (c, Circuit m b c)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Circuit m b c -> b -> Event m (c, Circuit m b c)
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m b c
process b
b)
            (Maybe c, Circuit m a (Maybe c))
-> m (Maybe c, Circuit m a (Maybe c))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (c -> Maybe c
forall a. a -> Maybe a
Just c
c, Circuit m a (Maybe b)
whether' Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c)
forall (m :: * -> *) a b c.
MonadDES m =>
Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c)
>?> Circuit m b c
process')

-- | Like '<<<' but processes only the represented events.
(<?<) :: MonadDES m
         => Circuit m b c
         -- ^ process the event if it presents
         -> Circuit m a (Maybe b)
         -- ^ whether there is an event
         -> Circuit m a (Maybe c)
         -- ^ the resulting circuit that processes only the represented events
{-# INLINABLE (<?<) #-}
<?< :: forall (m :: * -> *) b c a.
MonadDES m =>
Circuit m b c -> Circuit m a (Maybe b) -> Circuit m a (Maybe c)
(<?<) = (Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c))
-> Circuit m b c -> Circuit m a (Maybe b) -> Circuit m a (Maybe c)
forall a b c. (a -> b -> c) -> b -> a -> c
flip Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c)
forall (m :: * -> *) a b c.
MonadDES m =>
Circuit m a (Maybe b) -> Circuit m b c -> Circuit m a (Maybe c)
(>?>)

-- | Filter the circuit, calculating only those parts of the circuit that satisfy
-- the specified predicate.
filterCircuit :: MonadDES m => (a -> Bool) -> Circuit m a b -> Circuit m a (Maybe b)
{-# INLINABLE filterCircuit #-}
filterCircuit :: forall (m :: * -> *) a b.
MonadDES m =>
(a -> Bool) -> Circuit m a b -> Circuit m a (Maybe b)
filterCircuit a -> Bool
pred = (a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
forall (m :: * -> *) a b.
MonadDES m =>
(a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
filterCircuitM (Bool -> Event m Bool
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Event m Bool) -> (a -> Bool) -> a -> Event m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
pred)

-- | Filter the circuit within the 'Event' computation, calculating only those parts
-- of the circuit that satisfy the specified predicate.
filterCircuitM :: MonadDES m => (a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
{-# INLINABLE filterCircuitM #-}
filterCircuitM :: forall (m :: * -> *) a b.
MonadDES m =>
(a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
filterCircuitM a -> Event m Bool
pred Circuit m a b
cir =
  (a -> Event m (Maybe b, Circuit m a (Maybe b)))
-> Circuit m a (Maybe b)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (Maybe b, Circuit m a (Maybe b)))
 -> Circuit m a (Maybe b))
-> (a -> Event m (Maybe b, Circuit m a (Maybe b)))
-> Circuit m a (Maybe b)
forall a b. (a -> b) -> a -> b
$ \a
a ->
  (Point m -> m (Maybe b, Circuit m a (Maybe b)))
-> Event m (Maybe b, Circuit m a (Maybe b))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Maybe b, Circuit m a (Maybe b)))
 -> Event m (Maybe b, Circuit m a (Maybe b)))
-> (Point m -> m (Maybe b, Circuit m a (Maybe b)))
-> Event m (Maybe b, Circuit m a (Maybe b))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Bool
x <- Point m -> Event m Bool -> m Bool
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (a -> Event m Bool
pred a
a)
     if Bool
x
       then do (b
b, Circuit m a b
cir') <- Point m -> Event m (b, Circuit m a b) -> m (b, Circuit m a b)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Circuit m a b -> a -> Event m (b, Circuit m a b)
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a b
cir a
a)
               (Maybe b, Circuit m a (Maybe b))
-> m (Maybe b, Circuit m a (Maybe b))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Maybe b
forall a. a -> Maybe a
Just b
b, (a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
forall (m :: * -> *) a b.
MonadDES m =>
(a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
filterCircuitM a -> Event m Bool
pred Circuit m a b
cir')
       else (Maybe b, Circuit m a (Maybe b))
-> m (Maybe b, Circuit m a (Maybe b))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe b
forall a. Maybe a
Nothing, (a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
forall (m :: * -> *) a b.
MonadDES m =>
(a -> Event m Bool) -> Circuit m a b -> Circuit m a (Maybe b)
filterCircuitM a -> Event m Bool
pred Circuit m a b
cir)

-- | The source of events that never occur.
neverCircuit :: MonadDES m => Circuit m a (Maybe b)
{-# INLINABLE neverCircuit #-}
neverCircuit :: forall (m :: * -> *) a b. MonadDES m => Circuit m a (Maybe b)
neverCircuit =
  (a -> Event m (Maybe b, Circuit m a (Maybe b)))
-> Circuit m a (Maybe b)
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (Maybe b, Circuit m a (Maybe b)))
 -> Circuit m a (Maybe b))
-> (a -> Event m (Maybe b, Circuit m a (Maybe b)))
-> Circuit m a (Maybe b)
forall a b. (a -> b) -> a -> b
$ \a
a -> (Maybe b, Circuit m a (Maybe b))
-> Event m (Maybe b, Circuit m a (Maybe b))
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe b
forall a. Maybe a
Nothing, Circuit m a (Maybe b)
forall (m :: * -> *) a b. MonadDES m => Circuit m a (Maybe b)
neverCircuit)

-- | An approximation of the integral using Euler's method.
--
-- This function can be rather inaccurate as it depends on
-- the time points at wich the 'Circuit' computation is actuated.
-- Also Euler's method per se is not most accurate, although simple
-- enough for implementation.
--
-- Consider using the 'integ' function whenever possible.
-- That function can integrate with help of the Runge-Kutta method by
-- the specified integration time points that are passed in the simulation
-- specs to every 'Simulation', when running the model.
--
-- At the same time, the 'integCircuit' function has no mutable state
-- unlike the former. The latter consumes less memory but at the cost
-- of inaccuracy and relatively more slow simulation, had we requested
-- the integral in the same time points.
--
-- Regarding the recursive equations, the both functions allow defining them
-- but whithin different computations (either with help of the recursive
-- do-notation or the proc-notation).
integCircuit :: MonadDES m
                => Double
                -- ^ the initial value
                -> Circuit m Double Double
                -- ^ map the derivative to an integral
{-# INLINABLE integCircuit #-}
integCircuit :: forall (m :: * -> *).
MonadDES m =>
Double -> Circuit m Double Double
integCircuit Double
init = Circuit m Double Double
start
  where
    start :: Circuit m Double Double
start = 
      (Double -> Event m (Double, Circuit m Double Double))
-> Circuit m Double Double
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Double -> Event m (Double, Circuit m Double Double))
 -> Circuit m Double Double)
-> (Double -> Event m (Double, Circuit m Double Double))
-> Circuit m Double Double
forall a b. (a -> b) -> a -> b
$ \Double
a ->
      (Point m -> m (Double, Circuit m Double Double))
-> Event m (Double, Circuit m Double Double)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Double, Circuit m Double Double))
 -> Event m (Double, Circuit m Double Double))
-> (Point m -> m (Double, Circuit m Double Double))
-> Event m (Double, Circuit m Double Double)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      do let t :: Double
t = Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p
         (Double, Circuit m Double Double)
-> m (Double, Circuit m Double Double)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
init, Double -> Double -> Double -> Circuit m Double Double
forall {m :: * -> *}.
Monad m =>
Double -> Double -> Double -> Circuit m Double Double
next Double
t Double
init Double
a)
    next :: Double -> Double -> Double -> Circuit m Double Double
next Double
t0 Double
v0 Double
a0 =
      (Double -> Event m (Double, Circuit m Double Double))
-> Circuit m Double Double
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Double -> Event m (Double, Circuit m Double Double))
 -> Circuit m Double Double)
-> (Double -> Event m (Double, Circuit m Double Double))
-> Circuit m Double Double
forall a b. (a -> b) -> a -> b
$ \Double
a ->
      (Point m -> m (Double, Circuit m Double Double))
-> Event m (Double, Circuit m Double Double)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Double, Circuit m Double Double))
 -> Event m (Double, Circuit m Double Double))
-> (Point m -> m (Double, Circuit m Double Double))
-> Event m (Double, Circuit m Double Double)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      do let t :: Double
t  = Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p
             dt :: Double
dt = Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
t0
             v :: Double
v  = Double
v0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
a0 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
dt
         Double
v Double
-> m (Double, Circuit m Double Double)
-> m (Double, Circuit m Double Double)
forall a b. a -> b -> b
`seq` (Double, Circuit m Double Double)
-> m (Double, Circuit m Double Double)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
v, Double -> Double -> Double -> Circuit m Double Double
next Double
t Double
v Double
a)

-- | Like 'integCircuit' but allows either setting a new 'Left' integral value,
-- or using the 'Right' derivative when integrating by Euler's method.
integCircuitEither :: MonadDES m
                      => Double
                      -- ^ the initial value
                      -> Circuit m (Either Double Double) Double
                      -- ^ map either a new 'Left' value or
                      -- the 'Right' derivative to an integral
{-# INLINABLE integCircuitEither #-}
integCircuitEither :: forall (m :: * -> *).
MonadDES m =>
Double -> Circuit m (Either Double Double) Double
integCircuitEither Double
init = Circuit m (Either Double Double) Double
start
  where
    start :: Circuit m (Either Double Double) Double
start = 
      (Either Double Double
 -> Event m (Double, Circuit m (Either Double Double) Double))
-> Circuit m (Either Double Double) Double
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either Double Double
  -> Event m (Double, Circuit m (Either Double Double) Double))
 -> Circuit m (Either Double Double) Double)
-> (Either Double Double
    -> Event m (Double, Circuit m (Either Double Double) Double))
-> Circuit m (Either Double Double) Double
forall a b. (a -> b) -> a -> b
$ \Either Double Double
a ->
      (Point m -> m (Double, Circuit m (Either Double Double) Double))
-> Event m (Double, Circuit m (Either Double Double) Double)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Double, Circuit m (Either Double Double) Double))
 -> Event m (Double, Circuit m (Either Double Double) Double))
-> (Point m -> m (Double, Circuit m (Either Double Double) Double))
-> Event m (Double, Circuit m (Either Double Double) Double)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      do let t :: Double
t = Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p
         (Double, Circuit m (Either Double Double) Double)
-> m (Double, Circuit m (Either Double Double) Double)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
init, Double
-> Double
-> Either Double Double
-> Circuit m (Either Double Double) Double
forall {m :: * -> *}.
Monad m =>
Double
-> Double
-> Either Double Double
-> Circuit m (Either Double Double) Double
next Double
t Double
init Either Double Double
a)
    next :: Double
-> Double
-> Either Double Double
-> Circuit m (Either Double Double) Double
next Double
t0 Double
v0 Either Double Double
a0 =
      (Either Double Double
 -> Event m (Double, Circuit m (Either Double Double) Double))
-> Circuit m (Either Double Double) Double
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either Double Double
  -> Event m (Double, Circuit m (Either Double Double) Double))
 -> Circuit m (Either Double Double) Double)
-> (Either Double Double
    -> Event m (Double, Circuit m (Either Double Double) Double))
-> Circuit m (Either Double Double) Double
forall a b. (a -> b) -> a -> b
$ \Either Double Double
a ->
      (Point m -> m (Double, Circuit m (Either Double Double) Double))
-> Event m (Double, Circuit m (Either Double Double) Double)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Double, Circuit m (Either Double Double) Double))
 -> Event m (Double, Circuit m (Either Double Double) Double))
-> (Point m -> m (Double, Circuit m (Either Double Double) Double))
-> Event m (Double, Circuit m (Either Double Double) Double)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      do let t :: Double
t = Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p
         case Either Double Double
a0 of
           Left Double
v ->
             Double
v Double
-> m (Double, Circuit m (Either Double Double) Double)
-> m (Double, Circuit m (Either Double Double) Double)
forall a b. a -> b -> b
`seq` (Double, Circuit m (Either Double Double) Double)
-> m (Double, Circuit m (Either Double Double) Double)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
v, Double
-> Double
-> Either Double Double
-> Circuit m (Either Double Double) Double
next Double
t Double
v Either Double Double
a)
           Right Double
a0 -> do
             let dt :: Double
dt = Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
t0
                 v :: Double
v  = Double
v0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
a0 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
dt
             Double
v Double
-> m (Double, Circuit m (Either Double Double) Double)
-> m (Double, Circuit m (Either Double Double) Double)
forall a b. a -> b -> b
`seq` (Double, Circuit m (Either Double Double) Double)
-> m (Double, Circuit m (Either Double Double) Double)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
v, Double
-> Double
-> Either Double Double
-> Circuit m (Either Double Double) Double
next Double
t Double
v Either Double Double
a)

-- | A sum of differences starting from the specified initial value.
--
-- Consider using the more accurate 'diffsum' function whener possible as
-- it is calculated in every integration time point specified by specs
-- passed in to every 'Simulation', when running the model.
--
-- At the same time, the 'sumCircuit' function has no mutable state and
-- it consumes less memory than the former.
--
-- Regarding the recursive equations, the both functions allow defining them
-- but whithin different computations (either with help of the recursive
-- do-notation or the proc-notation).
sumCircuit :: (MonadDES m, Num a)
              => a
              -- ^ the initial value
              -> Circuit m a a
              -- ^ map the difference to a sum
{-# INLINABLE sumCircuit #-}
sumCircuit :: forall (m :: * -> *) a. (MonadDES m, Num a) => a -> Circuit m a a
sumCircuit a
init = Circuit m a a
start
  where
    start :: Circuit m a a
start = 
      (a -> Event m (a, Circuit m a a)) -> Circuit m a a
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (a, Circuit m a a)) -> Circuit m a a)
-> (a -> Event m (a, Circuit m a a)) -> Circuit m a a
forall a b. (a -> b) -> a -> b
$ \a
a ->
      (Point m -> m (a, Circuit m a a)) -> Event m (a, Circuit m a a)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (a, Circuit m a a)) -> Event m (a, Circuit m a a))
-> (Point m -> m (a, Circuit m a a)) -> Event m (a, Circuit m a a)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      (a, Circuit m a a) -> m (a, Circuit m a a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
init, a -> a -> Circuit m a a
forall {m :: * -> *} {t}.
(Monad m, Num t) =>
t -> t -> Circuit m t t
next a
init a
a)
    next :: t -> t -> Circuit m t t
next t
v0 t
a0 =
      (t -> Event m (t, Circuit m t t)) -> Circuit m t t
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((t -> Event m (t, Circuit m t t)) -> Circuit m t t)
-> (t -> Event m (t, Circuit m t t)) -> Circuit m t t
forall a b. (a -> b) -> a -> b
$ \t
a ->
      (Point m -> m (t, Circuit m t t)) -> Event m (t, Circuit m t t)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (t, Circuit m t t)) -> Event m (t, Circuit m t t))
-> (Point m -> m (t, Circuit m t t)) -> Event m (t, Circuit m t t)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      do let v :: t
v = t
v0 t -> t -> t
forall a. Num a => a -> a -> a
+ t
a0
         t
v t -> m (t, Circuit m t t) -> m (t, Circuit m t t)
forall a b. a -> b -> b
`seq` (t, Circuit m t t) -> m (t, Circuit m t t)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (t
v, t -> t -> Circuit m t t
next t
v t
a)

-- | Like 'sumCircuit' but allows either setting a new 'Left' value for the sum, or updating it
-- by specifying the 'Right' difference.
sumCircuitEither :: (MonadDES m, Num a)
                    => a
                    -- ^ the initial value
                    -> Circuit m (Either a a) a
                    -- ^ map either a new 'Left' value or
                    -- the 'Right' difference to a sum
{-# INLINABLE sumCircuitEither #-}
sumCircuitEither :: forall (m :: * -> *) a.
(MonadDES m, Num a) =>
a -> Circuit m (Either a a) a
sumCircuitEither a
init = Circuit m (Either a a) a
start
  where
    start :: Circuit m (Either a a) a
start = 
      (Either a a -> Event m (a, Circuit m (Either a a) a))
-> Circuit m (Either a a) a
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either a a -> Event m (a, Circuit m (Either a a) a))
 -> Circuit m (Either a a) a)
-> (Either a a -> Event m (a, Circuit m (Either a a) a))
-> Circuit m (Either a a) a
forall a b. (a -> b) -> a -> b
$ \Either a a
a ->
      (Point m -> m (a, Circuit m (Either a a) a))
-> Event m (a, Circuit m (Either a a) a)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (a, Circuit m (Either a a) a))
 -> Event m (a, Circuit m (Either a a) a))
-> (Point m -> m (a, Circuit m (Either a a) a))
-> Event m (a, Circuit m (Either a a) a)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      (a, Circuit m (Either a a) a) -> m (a, Circuit m (Either a a) a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
init, a -> Either a a -> Circuit m (Either a a) a
forall {m :: * -> *} {t}.
(Monad m, Num t) =>
t -> Either t t -> Circuit m (Either t t) t
next a
init Either a a
a)
    next :: t -> Either t t -> Circuit m (Either t t) t
next t
v0 Either t t
a0 =
      (Either t t -> Event m (t, Circuit m (Either t t) t))
-> Circuit m (Either t t) t
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((Either t t -> Event m (t, Circuit m (Either t t) t))
 -> Circuit m (Either t t) t)
-> (Either t t -> Event m (t, Circuit m (Either t t) t))
-> Circuit m (Either t t) t
forall a b. (a -> b) -> a -> b
$ \Either t t
a ->
      (Point m -> m (t, Circuit m (Either t t) t))
-> Event m (t, Circuit m (Either t t) t)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (t, Circuit m (Either t t) t))
 -> Event m (t, Circuit m (Either t t) t))
-> (Point m -> m (t, Circuit m (Either t t) t))
-> Event m (t, Circuit m (Either t t) t)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      case Either t t
a0 of
        Left t
v ->
          t
v t
-> m (t, Circuit m (Either t t) t)
-> m (t, Circuit m (Either t t) t)
forall a b. a -> b -> b
`seq` (t, Circuit m (Either t t) t) -> m (t, Circuit m (Either t t) t)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (t
v, t -> Either t t -> Circuit m (Either t t) t
next t
v Either t t
a)
        Right t
a0 -> do
          let v :: t
v = t
v0 t -> t -> t
forall a. Num a => a -> a -> a
+ t
a0
          t
v t
-> m (t, Circuit m (Either t t) t)
-> m (t, Circuit m (Either t t) t)
forall a b. a -> b -> b
`seq` (t, Circuit m (Either t t) t) -> m (t, Circuit m (Either t t) t)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (t
v, t -> Either t t -> Circuit m (Either t t) t
next t
v Either t t
a)

-- | Approximate the circuit as a transform of time varying function,
-- calculating the values in the integration time points and then
-- interpolating in all other time points. The resulting transform
-- computation is synchronized with the event queue.         
--
-- This procedure consumes memory as the underlying memoization allocates
-- an array to store the calculated values.
circuitTransform :: (MonadSD m, MonadDES m) => Circuit m a b -> Transform m a b
{-# INLINABLE circuitTransform #-}
circuitTransform :: forall (m :: * -> *) a b.
(MonadSD m, MonadDES m) =>
Circuit m a b -> Transform m a b
circuitTransform Circuit m a b
cir = (Dynamics m a -> Simulation m (Dynamics m b)) -> Transform m a b
forall (m :: * -> *) a b.
(Dynamics m a -> Simulation m (Dynamics m b)) -> Transform m a b
Transform Dynamics m a -> Simulation m (Dynamics m b)
start
  where
    start :: Dynamics m a -> Simulation m (Dynamics m b)
start Dynamics m a
m =
      (Run m -> m (Dynamics m b)) -> Simulation m (Dynamics m b)
forall (m :: * -> *) a. (Run m -> m a) -> Simulation m a
Simulation ((Run m -> m (Dynamics m b)) -> Simulation m (Dynamics m b))
-> (Run m -> m (Dynamics m b)) -> Simulation m (Dynamics m b)
forall a b. (a -> b) -> a -> b
$ \Run m
r ->
      do Ref m (Circuit m a b)
ref <- Run m
-> Simulation m (Ref m (Circuit m a b))
-> m (Ref m (Circuit m a b))
forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r (Simulation m (Ref m (Circuit m a b)) -> m (Ref m (Circuit m a b)))
-> Simulation m (Ref m (Circuit m a b))
-> m (Ref m (Circuit m a b))
forall a b. (a -> b) -> a -> b
$ Circuit m a b -> Simulation m (Ref m (Circuit m a b))
forall a. a -> Simulation m (Ref m a)
forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef Circuit m a b
cir
         Run m -> Simulation m (Dynamics m b) -> m (Dynamics m b)
forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r (Simulation m (Dynamics m b) -> m (Dynamics m b))
-> Simulation m (Dynamics m b) -> m (Dynamics m b)
forall a b. (a -> b) -> a -> b
$
           Dynamics m b -> Simulation m (Dynamics m b)
forall e. Dynamics m e -> Simulation m (Dynamics m e)
forall (m :: * -> *) e.
MonadMemo m =>
Dynamics m e -> Simulation m (Dynamics m e)
memo0Dynamics (Ref m (Circuit m a b) -> Dynamics m a -> Dynamics m b
forall {m :: * -> *} {a} {a}.
(EventQueueing m, MonadRef m) =>
Ref m (Circuit m a a) -> Dynamics m a -> Dynamics m a
next Ref m (Circuit m a b)
ref Dynamics m a
m)
    next :: Ref m (Circuit m a a) -> Dynamics m a -> Dynamics m a
next Ref m (Circuit m a a)
ref Dynamics m a
m =
      (Point m -> m a) -> Dynamics m a
forall (m :: * -> *) a. (Point m -> m a) -> Dynamics m a
Dynamics ((Point m -> m a) -> Dynamics m a)
-> (Point m -> m a) -> Dynamics m a
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
      do a
a <- Point m -> Dynamics m a -> m a
forall (m :: * -> *) a. Point m -> Dynamics m a -> m a
invokeDynamics Point m
p Dynamics m a
m
         Point m -> Dynamics m a -> m a
forall (m :: * -> *) a. Point m -> Dynamics m a -> m a
invokeDynamics Point m
p (Dynamics m a -> m a) -> Dynamics m a -> m a
forall a b. (a -> b) -> a -> b
$
           Event m a -> Dynamics m a
forall a. Event m a -> Dynamics m a
forall (m :: * -> *) a.
EventQueueing m =>
Event m a -> Dynamics m a
runEvent (Event m a -> Dynamics m a) -> Event m a -> Dynamics m a
forall a b. (a -> b) -> a -> b
$
           (Point m -> m a) -> Event m a
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m a) -> Event m a) -> (Point m -> m a) -> Event m a
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
           do Circuit m a a
cir <- Point m -> Event m (Circuit m a a) -> m (Circuit m a a)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (Circuit m a a) -> m (Circuit m a a))
-> Event m (Circuit m a a) -> m (Circuit m a a)
forall a b. (a -> b) -> a -> b
$ Ref m (Circuit m a a) -> Event m (Circuit m a a)
forall a. Ref m a -> Event m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef Ref m (Circuit m a a)
ref
              (a
b, Circuit m a a
cir') <- Point m -> Event m (a, Circuit m a a) -> m (a, Circuit m a a)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (a, Circuit m a a) -> m (a, Circuit m a a))
-> Event m (a, Circuit m a a) -> m (a, Circuit m a a)
forall a b. (a -> b) -> a -> b
$ Circuit m a a -> a -> Event m (a, Circuit m a a)
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a a
cir a
a
              Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ Ref m (Circuit m a a) -> Circuit m a a -> Event m ()
forall a. Ref m a -> a -> Event m ()
forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef Ref m (Circuit m a a)
ref Circuit m a a
cir'
              a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
b

-- | Iterate the circuit in the specified time points.
iterateCircuitInPoints_ :: MonadDES m => [Point m] -> Circuit m a a -> a -> Event m ()
{-# INLINABLE iterateCircuitInPoints_ #-}
iterateCircuitInPoints_ :: forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a a -> a -> Event m ()
iterateCircuitInPoints_ [] Circuit m a a
cir a
a = () -> Event m ()
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
iterateCircuitInPoints_ (Point m
p : [Point m]
ps) Circuit m a a
cir a
a =
  Double -> EventPriority -> Event m () -> Event m ()
forall (m :: * -> *).
EventQueueing m =>
Double -> EventPriority -> Event m () -> Event m ()
enqueueEventWithPriority (Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p) (Point m -> EventPriority
forall (m :: * -> *). Point m -> EventPriority
pointPriority Point m
p) (Event m () -> Event m ()) -> Event m () -> Event m ()
forall a b. (a -> b) -> a -> b
$
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p' ->
  do (a
a', Circuit m a a
cir') <- Point m -> Event m (a, Circuit m a a) -> m (a, Circuit m a a)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (a, Circuit m a a) -> m (a, Circuit m a a))
-> Event m (a, Circuit m a a) -> m (a, Circuit m a a)
forall a b. (a -> b) -> a -> b
$ Circuit m a a -> a -> Event m (a, Circuit m a a)
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a a
cir a
a
     Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ [Point m] -> Circuit m a a -> a -> Event m ()
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a a -> a -> Event m ()
iterateCircuitInPoints_ [Point m]
ps Circuit m a a
cir' a
a'

-- | Iterate the circuit in the specified time points returning a task
-- which completes after the final output of the circuit is received.
iterateCircuitInPoints :: MonadDES m => [Point m] -> Circuit m a a -> a -> Event m (Task m a)
{-# INLINABLE iterateCircuitInPoints #-}
iterateCircuitInPoints :: forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a a -> a -> Event m (Task m a)
iterateCircuitInPoints [Point m]
ps Circuit m a a
cir a
a =
  do let loop :: [Point m] -> Circuit m t t -> t -> SignalSource m t -> Event m ()
loop [] Circuit m t t
cir t
a SignalSource m t
source = SignalSource m t -> t -> Event m ()
forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal SignalSource m t
source t
a
         loop (Point m
p : [Point m]
ps) Circuit m t t
cir t
a SignalSource m t
source =
           Double -> EventPriority -> Event m () -> Event m ()
forall (m :: * -> *).
EventQueueing m =>
Double -> EventPriority -> Event m () -> Event m ()
enqueueEventWithPriority (Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p) (Point m -> EventPriority
forall (m :: * -> *). Point m -> EventPriority
pointPriority Point m
p) (Event m () -> Event m ()) -> Event m () -> Event m ()
forall a b. (a -> b) -> a -> b
$
           (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p' ->
           do (t
a', Circuit m t t
cir') <- Point m -> Event m (t, Circuit m t t) -> m (t, Circuit m t t)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (t, Circuit m t t) -> m (t, Circuit m t t))
-> Event m (t, Circuit m t t) -> m (t, Circuit m t t)
forall a b. (a -> b) -> a -> b
$ Circuit m t t -> t -> Event m (t, Circuit m t t)
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m t t
cir t
a
              Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ [Point m] -> Circuit m t t -> t -> SignalSource m t -> Event m ()
loop [Point m]
ps Circuit m t t
cir' t
a' SignalSource m t
source
     SignalSource m a
source <- Simulation m (SignalSource m a) -> Event m (SignalSource m a)
forall a. Simulation m a -> Event m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
SimulationLift t m =>
Simulation m a -> t m a
liftSimulation Simulation m (SignalSource m a)
forall (m :: * -> *) a.
MonadDES m =>
Simulation m (SignalSource m a)
newSignalSource
     Task m a
task <- Process m a -> Event m (Task m a)
forall (m :: * -> *) a.
MonadDES m =>
Process m a -> Event m (Task m a)
runTask (Process m a -> Event m (Task m a))
-> Process m a -> Event m (Task m a)
forall a b. (a -> b) -> a -> b
$ Signal m a -> Process m a
forall (m :: * -> *) a. MonadDES m => Signal m a -> Process m a
processAwait (Signal m a -> Process m a) -> Signal m a -> Process m a
forall a b. (a -> b) -> a -> b
$ SignalSource m a -> Signal m a
forall (m :: * -> *) a. SignalSource m a -> Signal m a
publishSignal SignalSource m a
source
     [Point m] -> Circuit m a a -> a -> SignalSource m a -> Event m ()
forall {m :: * -> *} {t}.
(EventQueueing m, Monad m) =>
[Point m] -> Circuit m t t -> t -> SignalSource m t -> Event m ()
loop [Point m]
ps Circuit m a a
cir a
a SignalSource m a
source
     Task m a -> Event m (Task m a)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return Task m a
task

-- | Iterate the circuit in the integration time points.
iterateCircuitInIntegTimes_ :: MonadDES m => Circuit m a a -> a -> Event m ()
{-# INLINABLE iterateCircuitInIntegTimes_ #-}
iterateCircuitInIntegTimes_ :: forall (m :: * -> *) a.
MonadDES m =>
Circuit m a a -> a -> Event m ()
iterateCircuitInIntegTimes_ Circuit m a a
cir a
a =
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = Point m -> [Point m]
forall (m :: * -> *). Point m -> [Point m]
integPointsStartingFrom Point m
p
     Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ 
       [Point m] -> Circuit m a a -> a -> Event m ()
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a a -> a -> Event m ()
iterateCircuitInPoints_ [Point m]
ps Circuit m a a
cir a
a

-- | Iterate the circuit in the specified time points.
iterateCircuitInTimes_ :: MonadDES m => [Double] -> Circuit m a a -> a -> Event m ()
{-# INLINABLE iterateCircuitInTimes_ #-}
iterateCircuitInTimes_ :: forall (m :: * -> *) a.
MonadDES m =>
[Double] -> Circuit m a a -> a -> Event m ()
iterateCircuitInTimes_ [Double]
ts Circuit m a a
cir a
a =
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = (Double -> Point m) -> [Double] -> [Point m]
forall a b. (a -> b) -> [a] -> [b]
map (\Double
t -> Run m -> Double -> EventPriority -> Point m
forall (m :: * -> *). Run m -> Double -> EventPriority -> Point m
pointAt (Point m -> Run m
forall (m :: * -> *). Point m -> Run m
pointRun Point m
p) Double
t EventPriority
0) [Double]
ts
     Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ 
       [Point m] -> Circuit m a a -> a -> Event m ()
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a a -> a -> Event m ()
iterateCircuitInPoints_ [Point m]
ps Circuit m a a
cir a
a 

-- | Iterate the circuit in the integration time points returning a task
-- which completes after the final output of the circuit is received.
iterateCircuitInIntegTimes :: MonadDES m => Circuit m a a -> a -> Event m (Task m a)
{-# INLINABLE iterateCircuitInIntegTimes #-}
iterateCircuitInIntegTimes :: forall (m :: * -> *) a.
MonadDES m =>
Circuit m a a -> a -> Event m (Task m a)
iterateCircuitInIntegTimes Circuit m a a
cir a
a =
  (Point m -> m (Task m a)) -> Event m (Task m a)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Task m a)) -> Event m (Task m a))
-> (Point m -> m (Task m a)) -> Event m (Task m a)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = Point m -> [Point m]
forall (m :: * -> *). Point m -> [Point m]
integPointsStartingFrom Point m
p
     Point m -> Event m (Task m a) -> m (Task m a)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (Task m a) -> m (Task m a))
-> Event m (Task m a) -> m (Task m a)
forall a b. (a -> b) -> a -> b
$ 
       [Point m] -> Circuit m a a -> a -> Event m (Task m a)
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a a -> a -> Event m (Task m a)
iterateCircuitInPoints [Point m]
ps Circuit m a a
cir a
a

-- | Iterate the circuit in the specified time points returning a task
-- which completes after the final output of the circuit is received.
iterateCircuitInTimes :: MonadDES m => [Double] -> Circuit m a a -> a -> Event m (Task m a)
{-# INLINABLE iterateCircuitInTimes #-}
iterateCircuitInTimes :: forall (m :: * -> *) a.
MonadDES m =>
[Double] -> Circuit m a a -> a -> Event m (Task m a)
iterateCircuitInTimes [Double]
ts Circuit m a a
cir a
a =
  (Point m -> m (Task m a)) -> Event m (Task m a)
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Task m a)) -> Event m (Task m a))
-> (Point m -> m (Task m a)) -> Event m (Task m a)
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = (Double -> Point m) -> [Double] -> [Point m]
forall a b. (a -> b) -> [a] -> [b]
map (\Double
t -> Run m -> Double -> EventPriority -> Point m
forall (m :: * -> *). Run m -> Double -> EventPriority -> Point m
pointAt (Point m -> Run m
forall (m :: * -> *). Point m -> Run m
pointRun Point m
p) Double
t EventPriority
0) [Double]
ts
     Point m -> Event m (Task m a) -> m (Task m a)
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (Task m a) -> m (Task m a))
-> Event m (Task m a) -> m (Task m a)
forall a b. (a -> b) -> a -> b
$ 
       [Point m] -> Circuit m a a -> a -> Event m (Task m a)
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a a -> a -> Event m (Task m a)
iterateCircuitInPoints [Point m]
ps Circuit m a a
cir a
a 

-- | Iterate the circuit in the specified time points, interrupting the iteration
-- immediately if 'Nothing' is returned within the 'Circuit' computation.
iterateCircuitInPointsMaybe :: MonadDES m => [Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
{-# INLINABLE iterateCircuitInPointsMaybe #-}
iterateCircuitInPointsMaybe :: forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
iterateCircuitInPointsMaybe [] Circuit m a (Maybe a)
cir a
a = () -> Event m ()
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
iterateCircuitInPointsMaybe (Point m
p : [Point m]
ps) Circuit m a (Maybe a)
cir a
a =
  Double -> EventPriority -> Event m () -> Event m ()
forall (m :: * -> *).
EventQueueing m =>
Double -> EventPriority -> Event m () -> Event m ()
enqueueEventWithPriority (Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p) (Point m -> EventPriority
forall (m :: * -> *). Point m -> EventPriority
pointPriority Point m
p) (Event m () -> Event m ()) -> Event m () -> Event m ()
forall a b. (a -> b) -> a -> b
$
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p' ->
  do (Maybe a
a', Circuit m a (Maybe a)
cir') <- Point m
-> Event m (Maybe a, Circuit m a (Maybe a))
-> m (Maybe a, Circuit m a (Maybe a))
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (Maybe a, Circuit m a (Maybe a))
 -> m (Maybe a, Circuit m a (Maybe a)))
-> Event m (Maybe a, Circuit m a (Maybe a))
-> m (Maybe a, Circuit m a (Maybe a))
forall a b. (a -> b) -> a -> b
$ Circuit m a (Maybe a)
-> a -> Event m (Maybe a, Circuit m a (Maybe a))
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a (Maybe a)
cir a
a
     case Maybe a
a' of
       Maybe a
Nothing -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
       Just a
a' ->
         Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ [Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
iterateCircuitInPointsMaybe [Point m]
ps Circuit m a (Maybe a)
cir' a
a'

-- | Iterate the circuit in the integration time points, interrupting the iteration
-- immediately if 'Nothing' is returned within the 'Circuit' computation.
iterateCircuitInIntegTimesMaybe :: MonadDES m => Circuit m a (Maybe a) -> a -> Event m ()
{-# INLINABLE iterateCircuitInIntegTimesMaybe #-}
iterateCircuitInIntegTimesMaybe :: forall (m :: * -> *) a.
MonadDES m =>
Circuit m a (Maybe a) -> a -> Event m ()
iterateCircuitInIntegTimesMaybe Circuit m a (Maybe a)
cir a
a =
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = Point m -> [Point m]
forall (m :: * -> *). Point m -> [Point m]
integPointsStartingFrom Point m
p
     Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ 
       [Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
iterateCircuitInPointsMaybe [Point m]
ps Circuit m a (Maybe a)
cir a
a

-- | Iterate the circuit in the specified time points, interrupting the iteration
-- immediately if 'Nothing' is returned within the 'Circuit' computation.
iterateCircuitInTimesMaybe :: MonadDES m => [Double] -> Circuit m a (Maybe a) -> a -> Event m ()
{-# INLINABLE iterateCircuitInTimesMaybe #-}
iterateCircuitInTimesMaybe :: forall (m :: * -> *) a.
MonadDES m =>
[Double] -> Circuit m a (Maybe a) -> a -> Event m ()
iterateCircuitInTimesMaybe [Double]
ts Circuit m a (Maybe a)
cir a
a =
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = (Double -> Point m) -> [Double] -> [Point m]
forall a b. (a -> b) -> [a] -> [b]
map (\Double
t -> Run m -> Double -> EventPriority -> Point m
forall (m :: * -> *). Run m -> Double -> EventPriority -> Point m
pointAt (Point m -> Run m
forall (m :: * -> *). Point m -> Run m
pointRun Point m
p) Double
t EventPriority
0) [Double]
ts
     Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ 
       [Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
forall (m :: * -> *) a.
MonadDES m =>
[Point m] -> Circuit m a (Maybe a) -> a -> Event m ()
iterateCircuitInPointsMaybe [Point m]
ps Circuit m a (Maybe a)
cir a
a

-- | Iterate the circuit in the specified time points returning a task
-- that computes the final output of the circuit either after all points
-- are exhausted, or after the 'Left' result of type @b@ is received,
-- which interrupts the computation immediately.
iterateCircuitInPointsEither :: MonadDES m => [Point m] -> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
{-# INLINABLE iterateCircuitInPointsEither #-}
iterateCircuitInPointsEither :: forall (m :: * -> *) a b.
MonadDES m =>
[Point m]
-> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
iterateCircuitInPointsEither [Point m]
ps Circuit m a (Either b a)
cir a
a =
  do let loop :: [Point m]
-> Circuit m a (Either a a)
-> Either a a
-> SignalSource m (Either a a)
-> Event m ()
loop [] Circuit m a (Either a a)
cir Either a a
ba SignalSource m (Either a a)
source = SignalSource m (Either a a) -> Either a a -> Event m ()
forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal SignalSource m (Either a a)
source Either a a
ba
         loop [Point m]
ps Circuit m a (Either a a)
cir ba :: Either a a
ba@(Left a
b) SignalSource m (Either a a)
source = SignalSource m (Either a a) -> Either a a -> Event m ()
forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal SignalSource m (Either a a)
source Either a a
ba 
         loop (Point m
p : [Point m]
ps) Circuit m a (Either a a)
cir (Right a
a) SignalSource m (Either a a)
source =
           Double -> EventPriority -> Event m () -> Event m ()
forall (m :: * -> *).
EventQueueing m =>
Double -> EventPriority -> Event m () -> Event m ()
enqueueEventWithPriority (Point m -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point m
p) (Point m -> EventPriority
forall (m :: * -> *). Point m -> EventPriority
pointPriority Point m
p) (Event m () -> Event m ()) -> Event m () -> Event m ()
forall a b. (a -> b) -> a -> b
$
           (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p' ->
           do (Either a a
ba', Circuit m a (Either a a)
cir') <- Point m
-> Event m (Either a a, Circuit m a (Either a a))
-> m (Either a a, Circuit m a (Either a a))
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (Either a a, Circuit m a (Either a a))
 -> m (Either a a, Circuit m a (Either a a)))
-> Event m (Either a a, Circuit m a (Either a a))
-> m (Either a a, Circuit m a (Either a a))
forall a b. (a -> b) -> a -> b
$ Circuit m a (Either a a)
-> a -> Event m (Either a a, Circuit m a (Either a a))
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a (Either a a)
cir a
a
              Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$ [Point m]
-> Circuit m a (Either a a)
-> Either a a
-> SignalSource m (Either a a)
-> Event m ()
loop [Point m]
ps Circuit m a (Either a a)
cir' Either a a
ba' SignalSource m (Either a a)
source
     SignalSource m (Either b a)
source <- Simulation m (SignalSource m (Either b a))
-> Event m (SignalSource m (Either b a))
forall a. Simulation m a -> Event m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
SimulationLift t m =>
Simulation m a -> t m a
liftSimulation Simulation m (SignalSource m (Either b a))
forall (m :: * -> *) a.
MonadDES m =>
Simulation m (SignalSource m a)
newSignalSource
     Task m (Either b a)
task <- Process m (Either b a) -> Event m (Task m (Either b a))
forall (m :: * -> *) a.
MonadDES m =>
Process m a -> Event m (Task m a)
runTask (Process m (Either b a) -> Event m (Task m (Either b a)))
-> Process m (Either b a) -> Event m (Task m (Either b a))
forall a b. (a -> b) -> a -> b
$ Signal m (Either b a) -> Process m (Either b a)
forall (m :: * -> *) a. MonadDES m => Signal m a -> Process m a
processAwait (Signal m (Either b a) -> Process m (Either b a))
-> Signal m (Either b a) -> Process m (Either b a)
forall a b. (a -> b) -> a -> b
$ SignalSource m (Either b a) -> Signal m (Either b a)
forall (m :: * -> *) a. SignalSource m a -> Signal m a
publishSignal SignalSource m (Either b a)
source
     [Point m]
-> Circuit m a (Either b a)
-> Either b a
-> SignalSource m (Either b a)
-> Event m ()
forall {m :: * -> *} {a} {a}.
(EventQueueing m, Monad m) =>
[Point m]
-> Circuit m a (Either a a)
-> Either a a
-> SignalSource m (Either a a)
-> Event m ()
loop [Point m]
ps Circuit m a (Either b a)
cir (a -> Either b a
forall a b. b -> Either a b
Right a
a) SignalSource m (Either b a)
source
     Task m (Either b a) -> Event m (Task m (Either b a))
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return Task m (Either b a)
task

-- | Iterate the circuit in the integration time points returning a task
-- that computes the final output of the circuit either after all points
-- are exhausted, or after the 'Left' result of type @b@ is received,
-- which interrupts the computation immediately.
iterateCircuitInIntegTimesEither :: MonadDES m => Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
{-# INLINABLE iterateCircuitInIntegTimesEither #-}
iterateCircuitInIntegTimesEither :: forall (m :: * -> *) a b.
MonadDES m =>
Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
iterateCircuitInIntegTimesEither Circuit m a (Either b a)
cir a
a =
  (Point m -> m (Task m (Either b a)))
-> Event m (Task m (Either b a))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Task m (Either b a)))
 -> Event m (Task m (Either b a)))
-> (Point m -> m (Task m (Either b a)))
-> Event m (Task m (Either b a))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = Point m -> [Point m]
forall (m :: * -> *). Point m -> [Point m]
integPointsStartingFrom Point m
p
     Point m -> Event m (Task m (Either b a)) -> m (Task m (Either b a))
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (Task m (Either b a)) -> m (Task m (Either b a)))
-> Event m (Task m (Either b a)) -> m (Task m (Either b a))
forall a b. (a -> b) -> a -> b
$ 
       [Point m]
-> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
forall (m :: * -> *) a b.
MonadDES m =>
[Point m]
-> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
iterateCircuitInPointsEither [Point m]
ps Circuit m a (Either b a)
cir a
a

-- | Iterate the circuit in the specified time points returning a task
-- that computes the final output of the circuit either after all points
-- are exhausted, or after the 'Left' result of type @b@ is received,
-- which interrupts the computation immediately.
iterateCircuitInTimesEither :: MonadDES m => [Double] -> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
{-# INLINABLE iterateCircuitInTimesEither #-}
iterateCircuitInTimesEither :: forall (m :: * -> *) a b.
MonadDES m =>
[Double]
-> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
iterateCircuitInTimesEither [Double]
ts Circuit m a (Either b a)
cir a
a =
  (Point m -> m (Task m (Either b a)))
-> Event m (Task m (Either b a))
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m (Task m (Either b a)))
 -> Event m (Task m (Either b a)))
-> (Point m -> m (Task m (Either b a)))
-> Event m (Task m (Either b a))
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let ps :: [Point m]
ps = (Double -> Point m) -> [Double] -> [Point m]
forall a b. (a -> b) -> [a] -> [b]
map (\Double
t -> Run m -> Double -> EventPriority -> Point m
forall (m :: * -> *). Run m -> Double -> EventPriority -> Point m
pointAt (Point m -> Run m
forall (m :: * -> *). Point m -> Run m
pointRun Point m
p) Double
t EventPriority
0) [Double]
ts
     Point m -> Event m (Task m (Either b a)) -> m (Task m (Either b a))
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m (Task m (Either b a)) -> m (Task m (Either b a)))
-> Event m (Task m (Either b a)) -> m (Task m (Either b a))
forall a b. (a -> b) -> a -> b
$ 
       [Point m]
-> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
forall (m :: * -> *) a b.
MonadDES m =>
[Point m]
-> Circuit m a (Either b a) -> a -> Event m (Task m (Either b a))
iterateCircuitInPointsEither [Point m]
ps Circuit m a (Either b a)
cir a
a

-- | Show the debug messages with the current simulation time.
traceCircuit :: MonadDES m
                => Maybe String
                -- ^ the request message
                -> Maybe String
                -- ^ the response message
                -> Circuit m a b
                -- ^ a circuit
                -> Circuit m a b
{-# INLINABLE traceCircuit #-}
traceCircuit :: forall (m :: * -> *) a b.
MonadDES m =>
Maybe String -> Maybe String -> Circuit m a b -> Circuit m a b
traceCircuit Maybe String
request Maybe String
response Circuit m a b
cir = (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (b, Circuit m a b)) -> Circuit m a b)
-> (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall a b. (a -> b) -> a -> b
$ Circuit m a b -> a -> Event m (b, Circuit m a b)
forall {m :: * -> *} {a} {b}.
MonadDES m =>
Circuit m a b -> a -> Event m (b, Circuit m a b)
loop Circuit m a b
cir where
  loop :: Circuit m a b -> a -> Event m (b, Circuit m a b)
loop Circuit m a b
cir a
a =
    do (b
b, Circuit m a b
cir') <-
         case Maybe String
request of
           Maybe String
Nothing -> Circuit m a b -> a -> Event m (b, Circuit m a b)
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a b
cir a
a
           Just String
message -> 
             String -> Event m (b, Circuit m a b) -> Event m (b, Circuit m a b)
forall (m :: * -> *) a.
MonadDES m =>
String -> Event m a -> Event m a
traceEvent String
message (Event m (b, Circuit m a b) -> Event m (b, Circuit m a b))
-> Event m (b, Circuit m a b) -> Event m (b, Circuit m a b)
forall a b. (a -> b) -> a -> b
$
             Circuit m a b -> a -> Event m (b, Circuit m a b)
forall (m :: * -> *) a b.
Circuit m a b -> a -> Event m (b, Circuit m a b)
runCircuit Circuit m a b
cir a
a
       case Maybe String
response of
         Maybe String
Nothing -> (b, Circuit m a b) -> Event m (b, Circuit m a b)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (b, Circuit m a b)) -> Circuit m a b)
-> (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall a b. (a -> b) -> a -> b
$ Circuit m a b -> a -> Event m (b, Circuit m a b)
loop Circuit m a b
cir')
         Just String
message ->
           String -> Event m (b, Circuit m a b) -> Event m (b, Circuit m a b)
forall (m :: * -> *) a.
MonadDES m =>
String -> Event m a -> Event m a
traceEvent String
message (Event m (b, Circuit m a b) -> Event m (b, Circuit m a b))
-> Event m (b, Circuit m a b) -> Event m (b, Circuit m a b)
forall a b. (a -> b) -> a -> b
$
           (b, Circuit m a b) -> Event m (b, Circuit m a b)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall (m :: * -> *) a b.
(a -> Event m (b, Circuit m a b)) -> Circuit m a b
Circuit ((a -> Event m (b, Circuit m a b)) -> Circuit m a b)
-> (a -> Event m (b, Circuit m a b)) -> Circuit m a b
forall a b. (a -> b) -> a -> b
$ Circuit m a b -> a -> Event m (b, Circuit m a b)
loop Circuit m a b
cir')