elerea-0.1.0: A minimalistic FRP library



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.



type Time = 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 represented as a transactional structural node.


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.

Eq (Signal a)

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

Fractional t => Fractional (Signal t) 
Num t => Num (Signal t) 
Show (Signal a)

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



:: Signal a

the top-level signal

-> DTime

the amount of time to advance

-> IO a

the value of the signal before the update

Advancing the whole network that the given signal depends on by the amount of time given in the second argument. Note that the shared time signal is also advanced, so this function should only be used for sampling the top level.

time :: Signal TimeSource

The global time.



:: (Time -> a)

the function to wrap

-> Signal a 

A pure time function.



:: a

initial state

-> (DTime -> a -> a)

state transformation

-> Signal a 

A pure stateful signal.



:: a

initial state

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

state updater function

-> Signal t

input signal

-> Signal a 

A stateful transfer function. The current input can only affect the next output, i.e. there is an implicit delay.



:: Signal a

s: initial behaviour

-> Signal Bool

e: latch control signal

-> Signal (Signal a)

ss: signal of potential future behaviours

-> Signal a 

Reactive signal that starts out as s and can change its behaviour to the one supplied in ss whenever e is true. The change can only be observed in the next instant.



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