"Combines two [[promises|Promise]] into a new promise. The new promise is - fulfilled when both promises are fulfilled, or - rejected when either of the two promises is rejected." by("Julien Viet") class Conjunction<out Element, out First, Rest>(first, rest) satisfies Completion<Element,Tuple<First|Element,First,Rest>> given First satisfies Element given Rest satisfies Sequential<Element> { "The first promise." Promise<Rest> rest; "The second promise." Promise<First> first; // We use the context of the first value deferred = Deferred<Tuple<First|Element,First,Rest>> (first.context); promise = deferred.promise; variable First? firstVal = null; variable Rest? restVal = null; void check() { if (exists first = firstVal, exists rest = restVal) { deferred.fulfill(Tuple(first, rest)); } } void onReject(Throwable e) { deferred.reject(e); } void onRestFulfilled(Rest val) { restVal = val; check(); } rest.map(onRestFulfilled, onReject); void onFirstFulfilled(First val) { firstVal = val; check(); } first.map(onFirstFulfilled, onReject); shared actual Completion<Element|Other,Tuple<Element|Other,Other,Tuple<First|Element,First,Rest>>> and<Other>(Promise<Other> other) => Conjunction(other, promise); shared actual Promise<Result> map<Result>( Result(*Tuple<First|Element,First,Rest>) onFulfilled, Result(Throwable) onRejected) => promise.map { (Tuple<First|Element,First,Rest> args) => unflatten(onFulfilled)(args); onRejected; }; shared actual Promise<Result> flatMap<Result>( Promise<Result>(*Tuple<First|Element,First,Rest>) onFulfilled, Promise<Result>(Throwable) onRejected) => promise.flatMap { (Tuple<First|Element,First,Rest> args) => unflatten(onFulfilled)(args); onRejected; }; }