{-| Elerea (Eventless Reactivity) is a simplistic FRP implementation that parts with the concept of events, and uses a continuous latching construct instead. The user sees the functionality through an applicative interface, which is used to build up a network of interconnected mutable references. The network is executed iteratively, where each superstep consists of two phases: sampling-aging and finalisation. As an example, the following code is a possible way to define an approximation of our beloved trig functions: @ sine = integral 0 cosine cosine = integral 1 (-sine) @ Note that @integral@ is not a primitive, it can be defined by the user as a transfer function. A possible implementation that can be used on any 'Fractional' signal looks like this: @ integral x0 s = transfer x0 (\\dt x x0 -> x0+x*realToFrac dt) s @ Head to "FRP.Elerea.Internal" for the implementation details. To get a general idea how to use the library, check out the sources in the @elerea-examples@ package. -} module FRP.Elerea ( Time, DTime, Sink, Signal, superstep, stateful, transfer, latcher, external, delay, edge, (==@), (/=@), (<@), (<=@), (>=@), (>@), (&&@), (||@) ) where import Control.Applicative import FRP.Elerea.Internal infix 4 ==@, /=@, <@, <=@, >=@, >@ infixr 3 &&@ infixr 2 ||@ {-| The `delay` transfer function emits the value of a signal from the previous superstep, starting with the filler value `v0`. -} delay :: a -> Signal a -> Signal a delay v0 s = snd <$> transfer (v0,undefined) (\_ v' (v,_) -> (v',v)) s {-| The `edge` transfer function takes a bool signal and emits another bool signal that turns true only at the moment when there is a rising edge on the input. -} edge :: Signal Bool -> Signal Bool edge b = (not <$> delay True b) &&@ b {-| Point-wise equality of two signals. -} (==@) :: Eq a => Signal a -> Signal a -> Signal Bool (==@) = liftA2 (==) {-| Point-wise inequality of two signals. -} (/=@) :: Eq a => Signal a -> Signal a -> Signal Bool (/=@) = liftA2 (/=) {-| Point-wise comparison of two signals. -} (<@) :: Ord a => Signal a -> Signal a -> Signal Bool (<@) = liftA2 (<) {-| Point-wise comparison of two signals. -} (<=@) :: Ord a => Signal a -> Signal a -> Signal Bool (<=@) = liftA2 (<=) {-| Point-wise comparison of two signals. -} (>=@) :: Ord a => Signal a -> Signal a -> Signal Bool (>=@) = liftA2 (>=) {-| Point-wise comparison of two signals. -} (>@) :: Ord a => Signal a -> Signal a -> Signal Bool (>@) = liftA2 (>) {-| Point-wise OR of two boolean signals. -} (||@) :: Signal Bool -> Signal Bool -> Signal Bool (||@) = liftA2 (||) {-| Point-wise AND of two boolean signals. -} (&&@) :: Signal Bool -> Signal Bool -> Signal Bool (&&@) = liftA2 (&&)