Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is Elm's Signal's (Conal's Behaviors's) equivalent in RX ? Does RX have such a concept at all?

I was watching this video (see image below) and it made me wonder whether Elm's Signal is the same as Conal's Behaviour.

I think they are the same but I am not 100% sure. Are they the same?

Here are a few related questions:

1) What is a Elm's Signal (Conal's Behaviour) in RX ? Is there such a concept in RX at all? Perhaps ReplaySubject?

2) How can I turn an RX Observable into a Signal (Behaviour) in RX ? In Sodium there is the hold function for this purpose.

3) What is RX's Observable ( AFAIK RX's Observable corresponds to Conal's Event ) in Elm? Is there such a thing in Elm?

Thanks for reading.

Here are the questions expressed in a table:

enter image description here

Snapshot from the Elm talk:

enter image description here

like image 996
jhegedus Avatar asked Jan 30 '15 15:01

jhegedus


2 Answers

Here is a partial answer :

Sodium author Stephen Blackheath writes :

Elm is an example of a system that has one type Signal that combines Stream and Cell.

Source: https://forums.manning.com/posts/list/35274.page

A note on about Sodium's naming convention:

Sodium's Stream is Conal's Event and Sodium's Cell is Conal's Behaviour.

EDIT:

RX BehaviorSubject = Conal's Behavior.

RX Observable = Conal's Event.

like image 74
jhegedus Avatar answered Nov 06 '22 05:11

jhegedus


I believe the answer to your question above is that potentially your initial assumptions are wrong. I believe that the observable sequence is (more) analogous to Behaviour and Signal (Vary over continuous time, can be/are infinite, synchronous by default). Conal seems to indicate that an Event is a specific state at a point in time, a "happening" e.g. "the event describing the first left-button press after time t0" [*1]

|Rx            |Conal   |ELM   |
|--------------|--------|------|
|T             |Event   | ?    |
|IObservable<T>|Behavior|Signal|

I believe that an Event in Conal's description is the actual value at a point in time. So be more specific, I think this is even more accurate

|Rx                         |Conal   |ELM   |
|---------------------------|--------|------|
|TimeStamp<T>               |Event   | ?    |
|ReplaySubject<TimeStamp<T>>|Behavior|Signal|

I believe that here a ReplaySubject<TimeStamp<T>> more closely represents a Behaviour as I understand it (contain state and time, can fetch value at a point in time). However as a ReplaySubject does not really allow you just pull the state from a point in time, they are not like-for-like. In my opinion, an EventStore is a closer match.

So to be clear, in my understanding an Observable Sequence (Rx IObservable<T>) and Conal's Behaviour share a similar definition up to a point. They both represent an ordered sequence of values over time. However in Rx, this is all an observable sequence is. Remembering that Rx is purely a library to allow you to query streams of events. There are some features that allow you to cache data (Replay/Buffer) or work with windows of data (Window/GroupJoin) and you can even enrich data with timestamps (TimeStamp/TimeInterval).

However where Conal's Behaviours diverge from Observable Sequences, is in it's features of persistence and historical querying. As I understand it, Conal's Behaviour in addition to Rx's features also specify that you are able to pluck a value of a sequence at any given point in time. For example with there was a price tick at time 00:00:01 of $1.23 and then another price tick at time 00:00:05 of $2.34, a consumer could ask for a value at time 00:00:02 and would be given back the value of $1.23 (the most recent value at the point in time).

time         [t1   ]  [t2]  [t3]  [t4]  [t5   ]
prices   ----[$1.23]--------------------[$2.34]--->

price@t2 -------------[$1.23]|

Rx doesn't provide any support for this, but one could go to great lengths to write custom operators to support this.

//A forced example of querying historical data.
// Be carefull as Replay() uses an unbounded buffer!
var source = Observable.Interval(TimeSpan.FromMilliseconds(250))
        .Timestamp()
        .Replay();
var connection = source.Connect();

var time2 = DateTimeOffset.Now+TimeSpan.FromSeconds(2);
var valueAtTime2 = source.TakeWhile(ts=>ts.Timestamp <= time2)
                         .LastAsync();

valueAtTime2.Dump();    //LinqPad feature to output the result

Systems that can (could?) support this kind of retrospective querying could be systems like CEP (Complex Event Processing) engines or EventStore style databases.

[*1]. http://conal.net/papers/icfp97/icfp97.pdf

like image 1
Lee Campbell Avatar answered Nov 06 '22 05:11

Lee Campbell