elerea-1.2.2: A minimalistic FRP library



This version differs from the parametric one in introducing autmatic delays. In practice, if a dependency loop involves a transfer primitive, it will be resolved during runtime even if transfer functions are not delayed by default.

The interface of this module differs from the old Elerea in the following ways:

  • the delta time argument is generalised to an arbitrary type, so it is possible to do without external altogether in case someone wants to do so;
  • there is no sampler any more, it is substituted by join, as signals are monads;
  • generator has been conceptually simplified, so it's a more basic primitive now;
  • all signals are aged regardless of whether they are sampled (i.e. their behaviour doesn't depend on the context any more);
  • the user needs to cache the results of applicative operations to be reused in multiple places explicitly using the memo combinator.



data Signal p a Source

A signal can be thought of as a function of type Nat -> a, and its Monad instance agrees with that intuition. Internally, is represented by a sampling computation.


Monad (Signal p) 
Functor (Signal p) 
Applicative (Signal p) 
Bounded t => Bounded (Signal p t) 
Enum t => Enum (Signal p t) 
Eq (Signal p a)

Equality test is impossible.

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

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

data SignalGen p a Source

A signal generator is the only source of stateful signals. Internally, computes a signal structure and adds the new variables to an existing update pool.



:: SignalGen p (Signal p a)

the generator of the top-level signal

-> IO (p -> IO a)

the computation to sample the signal

Embedding a signal into an IO environment. Repeated calls to the computation returned cause the whole network to be updated, and the current sample of the top-level signal is produced as a result. The computation accepts a global parameter that will be distributed to all signals. For instance, this can be the time step, if we want to model continuous-time signals.



:: a

initial value

-> IO (Signal p a, a -> IO ())

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. Note that this is optional, as all the input of the network can be fed in through the global parameter, although that is not really convenient for many signals.



:: a

initial output

-> Signal p a

the signal to delay

-> SignalGen p (Signal p 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.

stateful :: a -> (p -> a -> a) -> SignalGen p (Signal p a)Source

A pure stateful signal. The initial state is the first output, and every following output is calculated from the previous one and the value of the global parameter.

transfer :: a -> (p -> t -> a -> a) -> Signal p t -> SignalGen p (Signal p a)Source

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 never be observed. Every output is derived from the current value of the input signal, the global parameter and the previous output. The only exception is when a transfer function sits in a loop without a delay. In this case, a delay will be inserted at a single place during runtime (i.e. the previous output of the node affected will be reused) to resolve the circular dependency.



:: Signal p a

signal to memoise

-> SignalGen p (Signal p a) 

Memoising combinator. It can be used to cache results of applicative combinators in case they are used in several places. Other than that, it is equivalent to return.



:: Signal p (SignalGen p a)

a stream of generators to potentially run

-> SignalGen p (Signal p a) 

A reactive signal that takes the value to output from a monad carried by its input. It is possible to create new signals in the monad.

noise :: MTRandom a => Signal p aSource

A random signal. For efficiency reasons it is not guaranteed to read the same value when sampled several times in the same superstep. If you need consistent noise input, you can produce it through an external signal from whatever source you prefer.

getRandom :: MTRandom a => SignalGen p aSource

A random source within the SignalGen monad.

debug :: String -> SignalGen p ()Source

A printing action within the SignalGen monad.