A Challenge Problem for Promise Designers

Mark Miller erights at gmail.com
Sat Apr 27 09:48:09 PDT 2013


Cool. I think we (at least you and I) have agreement on default flattening
(#0).

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>
or
   promise<a> -> (a -> b) -> promise<b> // when b is not itself a promise
type

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 at gmail.com>wrote:

> On Sat, Apr 27, 2013 at 7:38 AM, Mark Miller <erights at gmail.com> wrote:
> > On Fri, Apr 26, 2013 at 1:51 PM, Tab Atkins Jr. <jackalmage at gmail.com>
> > wrote:
> >> On Fri, Apr 26, 2013 at 1:45 PM, Domenic Denicola
> >> <domenic at domenicdenicola.com> wrote:
> >> > From: Tab Atkins Jr. [jackalmage at 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

  Cheers,
  --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130427/6f6419ac/attachment-0001.html>


More information about the es-discuss mailing list