TeSSLa Basic Operators

TeSSLa's full expressiveness can be achieved with the five basic operators nil, unit, lift, last and delay. While in practical applications one wants to use all the operators available in the standard library, having a very small language core with a formal semantics is helpful for thorough theoretical analysis of the language.

nil and unit

The operator nil describes the empty stream without any events. It can be of any data type:

nil[T]: Events[T]

In the formal semantics we only add one constant stream, usually called unit which has exactly one event at timestamp zero. The the actual implementations however TeSSLa supports automatic conversion from any type of the data domain t: T to the corresponding event stream of type Events[T] which has exactly one event at timestamp zero carrying this value.

lift

The operator lift takes a function over the data domain and lifts it to a function over streams. The lifted function is applied for every timestamp where any of the input streams has at least one event. For all input streams without an event at that timestamp None is passed to the function.

lift[A, B, T](a: Events[A], b: Events[B], f: (Option[A], Option[B]) => Option[T]): Events[T]

The signatures shown in this guide are simplified. See the documentation of the standard library for all the details.

An example which uses this operator is the derived merge operator:

merge[T](a: Events[T], b: Events[T]): Events[T]

It takes two event streams and merges their events, prioritising the first one. It can be defined in TeSSLa as follows

def merge[T](x: Events[T], y: Events[T]) =
  lift(x, y, (a: Option[T], b: Option[T]) =>
    if isNone(a) then b else a)
Merge
in x: Events[Int]
in y: Events[Int]

def z = merge(x,y)
out z

Move the input events with the mouse to see how they effect the derived streams.

last

The operator last returns the last known value from a value stream v every time it is triggered by any event on r.

last[T, U](v: Events[T], r: Events[U]): Events[T]

The following example demonstrates how events can be sampled multiple times or ignored entirely depending on the event pattern on r. The last known values explicitly does not include the current value!

Last
in v: Events[Int]
in r: Events[Unit]
def z = last(v, r)
out z

Move the input events with the mouse to see how they effect the derived streams.

Signal lift can be defined in TeSSLa using lift and last:

def slift[A, B, T](a: Events[A], b: Events[b], f: (A, B) => T): Events[T] = {
  def a1 = merge(a, last(a, b))
  def b1 = merge(b, last(b, a))
  lift(a1, b1, (x: Option[A], y: Option[B]) =>
    if isNone(x) || isNone(y)
    then None[T]
    else Some(f(getSome(x), getSome(y))))
}
Signal Lift
in x: Events[Int]
in y: Events[Int]

def x1 = merge(x, last(x,y))
def y1 = merge(x, last(x,y))
def z = x + y
out z

Move the input events with the mouse to see how they effect the derived streams.

Filter can be defined in TeSSLa using lift and last, too:

def filter[T](x: Events[T], c: Events[Bool]): Events[T] = {
  def c1 = merge(c, last(c, x))
  lift(x, c1, (a: Option[T], b: Option[Bool]) =>
    if !isNone(b) && getSome(b) then a else None[T])
}
Filter
in c: Events[Bool]
in x: Events[Unit]

def c1 = merge(c, last(c, x))
def z = filter(x, c)
out z

Move the input events with the mouse to see how they effect the derived streams.

delay

The delay operator takes delays as its first argument. After a delay has passed, a unit event is emitted. A delay can only be set if a reset event is received via the second argument, or if an event is emitted on the output.

delay[U](d: Events[Time], r: Events[U]): Events[Unit]

The following examples demonstrates how this operator can be used to add additional events at timestamps which where not present in the input streams:

Delay
in d: Events[Int]
in r: Events[Unit]
def z = delay(d, r)
out z

Move the input events with the mouse to see how they effect the derived streams.

Recursive Equations

TeSSLa relates a set of input streams to a set of output streams via mutually recursive equations, which allows self-references to the past, e.g. a stream which counts (or aggregates) the numbers of events on the stream x is expressed in TeSSLa as follows:

Recursive Last
in x: Events[Int]
def c: Events[Int] = merge(last(c, x) + 1, 0)
out c
def s: Events[Int] = merge(last(s, x) + x, 0)
out s

Move the input events with the mouse to see how they effect the derived streams.

The last operator outputs the last known value of the count stream, on every event of the stream x. The base of the recursion is provided by merging with 0, which is a stream with one initial event of value 0. Since last only refers to events strictly lying in the past, the unique solution of such recursive equations can be computed incrementally.

Like last, the delay operator can be used in recursive equations, for example the following specification produces an infinite stream with an event every 5 time units. The merge is used to provide a base case for the recursion and const is used to map the value of the generated events to 5 so that they can be used as the new timeout value.

Recursive Delay
def p: Events[Unit] = merge((), delay(const(2, p), ()))
out p

This example has no external input stream, so this diagram is not interactive.

Note that although this specification does not have any explicit input stream, you still need to provide an artificial input to it if you use the TeSSLa interpreter, because you need to pass the information to the interpreter, how far the stream p with its infinitely many events should be evaluated. This concept is called progress in the literature.

In the next example we use an input stream instead of () to start the recursion. Hence the period will start with the first event on the external input stream. If we now use this external input stream to reset the delay, too, then we can adjust the running period with the external input stream:

Recursive Delay With Changing Frequency
in r: Events[Int]
def p: Events[Int] = merge(r, last(p, delay(p, r)))
out p

Move the input events with the mouse to see how they effect the derived streams.

You can find more information on TeSSLa's basic operators and their formal semantics in the scientific publications on TeSSLa.