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 Time = Double
 type DTime = Double
 type Sink a = a > IO ()
 data Signal a
 superstep :: Signal a > DTime > IO 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
 external :: a > IO (Signal a, Sink a)
 delay :: a > Signal a > Signal a
 edge :: Signal Bool > Signal Bool
 (==@) :: 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.
:: 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 is more or less equivalent to liftA2 const
, the
difference being that 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!).
A signal that can be directly fed through the sink function returned. This can be used to attach the network to the outer world.
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.