W3C home > Mailing lists > Public > public-script-coord@w3.org > April to June 2013

Re: A Challenge Problem for Promise Designers

From: Mark Miller <erights@gmail.com>
Date: Sat, 27 Apr 2013 09:48:09 -0700
Message-ID: <CAK5yZYhCOsSMHks7TaAaqoxvUo79VZ3y6JKjHABvMNpKwEnGPQ@mail.gmail.com>
To: "Tab Atkins Jr." <jackalmage@gmail.com>
Cc: Domenic Denicola <domenic@domenicdenicola.com>, David Bruant <bruant.d@gmail.com>, "Mark S. Miller" <erights@google.com>, "public-script-coord@w3.org" <public-script-coord@w3.org>, Dean Tribble <tribble@e-dean.com>, es-discuss <es-discuss@mozilla.org>
Cool. I think we (at least you and I) have agreement on default flattening

FWIW, the reason I'm surprised that you're calling this monadic is the need
for the dynamic test on 'as long as "b" isn't a Promise'. In other words,
the signature of .then (including the receiver and excluding the errback)
is overloaded as

   promise<a> -> (a -> promise<b>) -> promise<b>
   promise<a> -> (a -> b) -> promise<b> // when b is not itself a promise

My impression is that each of these overloads by itself is a different
monad operation and that testing the condition in the comment
violates parametricity. If these do correspond to two different monad
operations, then different laws cover each. A similar analysis applies to
Q(x) (aka Future.resolve(x)).

In any case, no matter. We agree (assimilation aside) that this is how
.then and Q should behave. Wonderful!

On Sat, Apr 27, 2013 at 9:28 AM, Tab Atkins Jr. <jackalmage@gmail.com>wrote:

> On Sat, Apr 27, 2013 at 7:38 AM, Mark Miller <erights@gmail.com> wrote:
> > On Fri, Apr 26, 2013 at 1:51 PM, Tab Atkins Jr. <jackalmage@gmail.com>
> > wrote:
> >> On Fri, Apr 26, 2013 at 1:45 PM, Domenic Denicola
> >> <domenic@domenicdenicola.com> wrote:
> >> > From: Tab Atkins Jr. [jackalmage@gmail.com]
> >> >> Shorter me: this is why I keep asking people who want flattening to
> >> >> actually provide an example of where flattening is useful, that
> isn't (a)
> >> >> assimilation, (b) a result of weird language semantics from some
> non-JS
> >> >> language, or (c) an authoring error.
> >> >
> >> > Since (multi-level) flattening only occurs for assimilation (per
> >> > Promises/A+ 1.1), it appears we have been talking past each other. All
> >> > examples of multi-level flattening will necessarily be examples of
> >> > assimilation.
> >>
> >> In that case, HUZZAH!  We've solved the problem!
> >
> >
> > We may have.
> >
> > When I argue for default flattening (#0 in my "What Are We Arguing
> About")
> > and you argue against, you claim default flattening is not monadic,
> which I
> > agree with. But then you go on to explain as "monadic" a semantics that
> > seems like default flattening to me. I am curious if you could define
> what
> > you mean by "monadic". I don't much care if we call a promise system
> > "monadic" or not, but let's not let a disagreement on this term obscure a
> > possible agreement on what promises should do.
> Hmm, that's strange.  I just mean "following the monad laws".  In
> other words, Promises are monads, with .then as the monadic operation,
> taking a function of type "a -> Promise<b>", and resulting in a new
> Promise.  (For convenience, .then() is also the functor operation,
> allowing its function to be of type "a -> b", as long as "b" isn't a
> Promise.  But that doesn't harm the monad-ness, as long as you follow
> the laws.)  Future.accept (or its equivalent in a final Promise spec)
> is the monadic lift operation.
> We don't expose it explicitly (though we could), but the monadic
> "join" operation takes a Promise<Promise<a>>, and returns a new
> promise that waits for both the inner and outer to accept, then
> accepts with the inner's state.  If either rejects, the output promise
> rejects with the same reason.
> Did you think I meant something else?  If so, what?  And, do you think
> I've made a mistake in describing the monadic properties of promises?
> If so, what?
> > As I made clear in my "What Are We Arguing About" email, I want to
> separate
> > the argument about default flattening (#0) from the argument about
> whether
> > promises-for-promises are possible (#1), and from arguments about
> thenables
> > and assimilation (#2,#3,#4).
> >
> > AFAICT, leaving aside operations that would explicitly create
> > promises-for-promises, i.e., "fulfill" (aka "accept"), I don't see how
> it is
> > possible to create promises-for-promises with the remaining operations
> you
> > and I seem to agree on: Q(x) (aka "Future.resolve(x)"), "then",
> "resolve",
> > "reject". If promise-for-promises cannot be made in the first place,
> then no
> > recursive unwrapping is required to take them apart. Specifically,
> > assimilation aside and API details aside, what about Q do you disagree
> with,
> > if anything?
> Correct - if you leave out the only promise constructor that can
> actually make promises-for-promises, you can't make
> promises-for-promises.  ^_^  Thus, recursive unwrapping, outside of
> the assimilation use-case, isn't useful, as it's very hard to nest
> promises unless you're doing it on purpose.  (And if you are doing it
> on purpose, it's potentially useful to have it act monadic.)
> > If we can narrow our remaining disagreements down to #1..#7, that would
> be
> > great progress. Yes, #1..#7 will still be a lot of work, but great
> progress
> > nonetheless. And I will leave to you and other to fight about what is and
> > isn't called "monadic" ;).
> No fights necessary, luckily - the monad laws are completely trivial,
> and it's easy to prove something does or doesn't obey them.
> ~TJ

Text by me above is hereby placed in the public domain

Received on Saturday, 27 April 2013 16:48:36 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 17:14:13 UTC