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: samplingaging 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
elereaexamples
package.
 type DTime = Double
 type Sink a = a > IO ()
 data Signal a
 superstep :: Signal a > DTime > IO a
 external :: a > IO (Signal a, Sink a)
 keepAlive :: Signal a > Signal t > Signal a
 (.@.) :: Signal a > Signal t > Signal a
 stateful :: a > (DTime > a > a) > Signal a
 transfer :: a > (DTime > t > a > a) > Signal t > Signal a
 latcher :: Signal a > Signal Bool > Signal (Signal a) > Signal a
 restarter :: (Void > Signal a) > Signal (Signal a)
 delay :: a > Signal a > Signal a
 edge :: Signal Bool > Signal Bool
 (==>) :: Void > a > a
 (==@) :: Eq a => Signal a > Signal a > Signal Bool
 (/=@) :: Eq a => Signal a > Signal a > Signal Bool
 (<@) :: Ord a => Signal a > Signal a > Signal Bool
 (<=@) :: Ord a => Signal a > Signal a > Signal Bool
 (>=@) :: Ord a => Signal a > Signal a > Signal Bool
 (>@) :: Ord a => Signal a > Signal a > Signal Bool
 (&&@) :: Signal Bool > Signal Bool > Signal Bool
 (@) :: Signal Bool > Signal Bool > Signal Bool
Documentation
A signal is represented as a transactional structural node.
Functor Signal  
Applicative Signal  The 
Eq (Signal a)  The equality test checks whether two signals are physically the same. 
Floating t => Floating (Signal t)  
Fractional t => Fractional (Signal t)  
Num t => Num (Signal t)  
Show (Signal a)  The 
:: Signal a  the toplevel 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 signal that can be directly fed through the sink function returned. This can be used to attach the network to the outer world.
:: 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 equivalent to (flip . liftA2 . flip) const
, as it
evaluates its second argument first.
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 
> 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.
:: Signal a 

> Signal Bool 

> Signal (Signal a) 

> 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 be observed immediately, unless the signal is sampled by
sampleDelayed
, which puts a delay on the latch control (but not on
the latched signal!).
Dependency injection to allow signals to be partly restarted,
notably the parts synthesised by the function passed to restarter
.
The function receives a dummy value that must not be evaluated (it is
undefined
), but the result should depend on it somehow to prevent
letfloating from memoising the result outside the function. Such a
dependency can be established with the ==>
operator. Effectively,
restarter
is a nonmemoising version of pure
limited to construct
higherorder signals.
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.
edge :: Signal Bool > Signal BoolSource
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.
An operator that ignores its first argument and returns the
second, but hides the fact that the first argument is not needed. It
is equivalent to flip const
, but it cannot be inlined.