elerea-1.2.0: A minimalistic FRP library



Elerea (Eventless Reactivity) is a simplistic FRP implementation that parts with the concept of events, and introduces various constructs that can be used to define completely dynamic higher-order dataflow networks. The user sees the functionality through a hybrid monadic-applicative interface, where stateful signals can only be created through a specialised monad, while most combinators are purely applicative. The combinators build up a network of interconnected mutable references in the background. The network is executed iteratively, where each superstep consists of three 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,cosine) <- mdo
   s <- integral 0 c
   c <- integral 1 (-s)
   return (s,c)

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.

The FRP.Elerea.Experimental branch provides a similar interface with a rather different underlying structure, which is likely to be more efficient.



type DTime = DoubleSource

Time is continuous. Nothing fancy.

type Sink a = a -> IO ()Source

Sinks are used when feeding input into peripheral-bound signals.

data Signal a Source

A signal is conceptually a time-varying value.


Functor Signal 
Applicative Signal

The Applicative instance with run-time optimisation. The <*> operator tries to move all the pure parts to its left side in order to flatten the structure, hence cutting down on book-keeping costs. Since applicatives are used with pure functions and lifted values most of the time, one can gain a lot by merging these nodes.

Bounded t => Bounded (Signal t) 
Enum t => Enum (Signal t) 
Eq (Signal a)

The equality test checks whether two signals are physically the same.

Floating t => Floating (Signal t) 
Fractional t => Fractional (Signal t) 
Integral t => Integral (Signal t) 
Num t => Num (Signal t) 
Ord t => Ord (Signal t) 
Real t => Real (Signal t) 
Show (Signal a)

The Show instance is only defined for the sake of Num...

data SignalMonad a Source

A restricted monad to create stateful signals in.



:: Signal a

the top-level signal

-> DTime

the amount of time to advance

-> IO a

the current value of the signal

Advancing the whole network that the given signal depends on by the amount of time given in the second argument.



:: a

initial value

-> IO (Signal a, Sink a)

the signal and an IO function to feed it

A signal that can be directly fed through the sink function returned. This can be used to attach the network to the outer world.



:: a

initial state

-> (DTime -> a -> a)

state transformation

-> SignalMonad (Signal a) 

A pure stateful signal. The initial state is the first output.



:: a

initial internal state

-> (DTime -> t -> a -> a)

state updater function

-> Signal t

input signal

-> SignalMonad (Signal a) 

A stateful transfer function. The current input affects the current output, i.e. the initial state given in the first argument is considered to appear before the first output, and can only be directly observed by the sampleDelayed function.



:: a

initial output

-> Signal a

the signal to delay

-> SignalMonad (Signal a) 

The delay transfer function emits the value of a signal from the previous superstep, starting with the filler value given in the first argument. It has to be a primitive, otherwise it could not be used to prevent automatic delays.



:: Signal (Signal a)

signal to flatten

-> Signal a 

A continuous sampler that flattens a higher-order signal by outputting its current snapshots.



:: Signal Bool

control (trigger) signal

-> Signal (SignalMonad a)

a stream of monads to potentially run

-> Signal (Maybe a) 

A reactive signal that takes the value to output from a monad carried by its input when a boolean control signal is true, otherwise it outputs Nothing. It is possible to create new signals in the monad and also to print debug messages.



:: a

Initial output

-> Signal (Maybe a)

Maybe signal to latch on

-> SignalMonad (Signal a) 

The storeJust transfer function behaves as a latch on a Maybe input: it keeps its state when the input is Nothing, and replaces it with the input otherwise.

toMaybe :: Bool -> a -> Maybe aSource

A helper function to wrap any value in a Maybe depending on a boolean condition.

edge :: Signal Bool -> SignalMonad (Signal Bool)Source

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.



:: Signal a

the actual output

-> Signal t

a signal guaranteed to age when this one is sampled

-> Signal a 

Dependency injection to allow aging signals whose output is not necessarily needed to produce the current sample of the first argument. It's equivalent to (flip . liftA2 . flip) const, as it evaluates its second argument first.

(.@.) :: Signal a -> Signal t -> Signal aSource

A short alternative name for keepAlive.

(==@) :: Eq a => Signal a -> Signal a -> Signal BoolSource

Point-wise equality of two signals.

(/=@) :: Eq a => Signal a -> Signal a -> Signal BoolSource

Point-wise inequality of two signals.

(<@) :: Ord a => Signal a -> Signal a -> Signal BoolSource

Point-wise comparison of two signals.

(<=@) :: Ord a => Signal a -> Signal a -> Signal BoolSource

Point-wise comparison of two signals.

(>=@) :: Ord a => Signal a -> Signal a -> Signal BoolSource

Point-wise comparison of two signals.

(>@) :: Ord a => Signal a -> Signal a -> Signal BoolSource

Point-wise comparison of two signals.

(&&@) :: Signal Bool -> Signal Bool -> Signal BoolSource

Point-wise AND of two boolean signals.

(||@) :: Signal Bool -> Signal Bool -> Signal BoolSource

Point-wise OR of two boolean signals.

signalDebug :: Show a => a -> SignalMonad ()Source

A printing function that can be used in the SignalMonad. Provided for debugging purposes.