That part I wouldn't be so sure about: in all monads, the .of equivalent
is effect-free (in an IO monad, it does no IO; in a non-determinism
monad, it is deterministic; in a failure/exception monad, it does not
fail; in a count-steps monad, it doesn't count).
If you look at those identity laws at the top again, you'll see that
Promise.of cannot introduce a delay for these laws to work out
(otherwise, the left- and right-hand sides would have different
numbers of ticks/turns).

As I said, the number of ticks is unobservable if you're writing
effect-free code.

In my use of the the term above, the "effect" of the Promise monad
would be to provide a value "maybe now, maybe later", and an
"effect-free" '.of' would be an already resolved Promise ("value
available now").

Adding ticks in operations that should allow for "effect-free" passing
of intermediate results is observable in slow-downs. That was the
topic of the blog post that got me to look into this in the first place
(performance issues with promise implementations, see thread opening message).

The point of insisting that promises implement a monadic interface
is that promises can reuse abstractions built for monads - that also
means that passing intermediate values around should not cause
additional delays. For instance, in the 'liftA2' example from one of the issue tracker threads:

https://github.com/promises-aplus/promises-spec/issues/94#issuecomment-16193265

there are several occurrences of '.then', via 'map' and 'ap', that should not delay the result by several additional turns - the only asynchrony in using 'liftA2' over promises should come from the promise parameters and possibly from the callback parameter.

However, you seem to be referring to side-effects instead (effects beyond returning a value in an expression, beyond the specified effect of a given monad).

Side-effect-free code is difficult to write in JS - I would be surprised if most promise implementations were not full of side-effects
(internal queues, shared pipelines, resolution). Also, so many
examples of using promises involve side-effects that this seems
to count as an established practice.

Which means that the additional code queuing will also be observable in code reorderings, not just delays. Which is, indeed,
the rationale for attempting to add delays in a normalized fashion,
as you state below:

If you're not writing effect-free code, then as I said before, keeping
the number of ticks the same regardless of the state of the promise
when you call .then() on it is important for consistency, so it's easy
to reason about how your code will run.

Given that many JS APIs still are heavily side-effect biased, we'll
need to take that into account. And in that world, adding delays in
parts of the promise API that should implement the common
monadic interface is very much observable, and will cause code written against this common interface to behave differently when
run over a promise than when run over another monad.

Claus

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to