Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the inverse of a promise?

A promise represents a value that might become available in the future (or fails to do so).

What I am looking for is a data type which represents an available value that might become unavailable in the future (possibly due to an error):

Promise a b = TransitionFromTo<PENDING, Either<value a, error b>>
??? a       = TransitionFromTo<value a, Either<ENDED, FAILED>> or
??? a b     = TransitionFromTo<value a, Either<ENDED, error b>>

Has such a concept (or similar) been explored already? Are there existing semantics or common idioms?

For example, it might represent an open database connection that will get closed. My particular use case would be representing a "mutable", i.e. variable-sized, set-like collections in FRP as a stream of such "ending values" - when an event occurs the value is added to the set and when the value "ends" it is removed.

I felt like representing this as a Signal<Option<value>> or {data = value, ended = Promise<null>} doesn't quite match it - the first case doesn't include the guarantee that the value finally settles to Nothing and the second has the data field still accessible after the end.

like image 597
Bergi Avatar asked Sep 28 '14 11:09

Bergi


2 Answers

In short - It's possible to model with an Async Generator.

In the DB connection example, conceptually you've got a sequence of DB connections, every time you access the value you're yielding (possibly asynchronously) a value from the sequence (a connection). Yielding can be asynchronous, and the value itself might be asynchronous too. The sequence might end (making it never available again) or it might always yield the result - it might remain pending and never yield another connection again.

It's worth mentioning that an async generator is a vast superset of the type you're after - it's much more expressive and is not the diret inverse.

In long - Inverse how?

You could inverse a promise in several different ways.

A promise is a singular temporal getter. That is it holds the following:

  • It represents a single value.
  • Its value is temporal (that is, time dependant).
  • It's a getter.

Quoting Kris's work on the temporality of promises:

An observer can subscribe to eventually see the value of a promise. They can do this before or after the promise has a value. Any number of observers can subscribe multiple times and any single observer can subscribe to the same promise multiple times.... Promises are broadcast. The law that no consumer can interfere with another consumer makes it impossible for promises to abort work in progress. A promise represents a result, not the work leading to that result.

The inverse of a promise in each of these regards is different.

  • A Deferred is a singular temporal setter. It is the dual of a promise and it allows setting a value similarly to how a promise allows getting it.

  • A Reader (more commonly called an observable) is the multiple version of a promise, and the temporal version of an iterable. It represents multiple values that are temporally coming. It's like a promise that can change its value.

  • A Value , one of out most used and primitive things is the synchronous version of a promise.

If you want something that is unlike a promise in all three - you need something more advanced. A Generator, is the inverse of a promise in that regard, it's a spatial, multivalued setter. It's the opposite of a promise in every such regard.

However, what you're talking of is something that's async in both regards, you want something that is both available/unavailable and changes value. That's an async generator, one of the more complex types in play here.

Your type needs to be similar to a generator that's async twice, once in having the next value and once in getting the value itself, I've asked a similar C# question here. Here is an interesting talk and lecture about it.

Basically you want a generator whose values and next() are asynchronous. It's rather complex and there are few things it models properly (for example - an infinite scroll where both the scrolling and the content are asynchronous).

In a sense, the sequence ending signals your value "not being available" anymore, and the sequence generating the next instance indicates your signal not being available temporally again.

I also recommend Erik Meijer's talk and Kris Kowal's GTOR about this subject.

like image 128
Benjamin Gruenbaum Avatar answered Sep 28 '22 20:09

Benjamin Gruenbaum


A promise is an ordered triple:

Time -> Notification -> Value

Its inverse must also be an ordered triple:

Value -> Notification -> Time

However, you don't want to be notified when the value begins to decay, which is immediately; instead, you want to be notified when the value has decayed.

Value -> Time -> Notification

Notification carries Dispose semantics. Actually, it'd be quite similar to IDisposable if it were defined as IDisposable<T>.

public interface IDisposable<T out>
{
  T Value { get; }
  IDisposable Subscribe(Action disposedAction);
  void Dispose();  // Not entirely necessary, perhaps.
}

It looks like a Frankenstein hybrid of Task<T> and IObservable<T>.

The async dual of IDisposable perhaps?

like image 45
Dave Sexton Avatar answered Sep 28 '22 19:09

Dave Sexton