Closed Raynos closed 11 years ago
P.S. Link to my summary gist: https://gist.github.com/ForbesLindesay/5392612
The corresponding arguments for will need to be a bit longer and include examples as those arguments are less well understood by the promises community.
Map can be implemented on top of then and of if we get it to flatten a single layer rather than multiple layers.
Say what?
map shouldn't do any flattening. Map should take a Promise and a function and return a Promise that runs the function over the result of the original Promise. Just like how map over an array works.
"map" comes from the Functor type. The Functor laws state that map should return a value of the same structure. So, take a Promise of x, run a function x -> y over it and get a Promise of y.
One way of thinking of "flatMap" is that it maps then flattens.
As I understand it, this bizarre "then" function would be written in terms of map and flatMap.
@ForbesLindesay as for limiting Identity of Identity. How far does it go? There's actual use cases for Optional Optional values. Or Either Either values. It also ruins parametricity, as @techtangents pointed out.
And it breaks the Monad laws.
@ForbesLindesay just s/Identity/Optional/g in my comment. You need to represent Optional Optional values.
function map(entity, fn) {
if (typeof entity.map === 'function') {
return entity.map(fn);
} else if (entity.chain === 'function') {
return entity.chain(function (val) { return entity.constructor.of(fn(val)); });
} else if (entity.then === 'function') {// && if then only flattens one layer, not multiple
return entity.then(function (val) { return entity.constructor.of(fn(val)); });
}
}
In answer to @techtangents' "say what?"
I still find the idea of an optional optional a bit weird, it would be hugely helpful if someone had an example, but I'll accept it for now.
That's really weird.
Return a promise which evaluates the original promise, but maps a function over it.
function map(promise, fn) {
return promise(function(x) {
callback(fn(x))
});
}
I still find the idea of an optional optional a bit weird, it would be hugely helpful if someone had an example, but I'll accept it for now.
Well, you can think of an Optional as a List of either zero or 1 elements. Now think of a List of Lists.
I still find the idea of an optional optional a bit weird, it would be hugely helpful if someone had an example
James Iry has an example of that:
You're writing a cache system (in the form of an associative map) in front of a persistent storage with nullable values. Question: how do you differentiate between "I haven't cached this value" from "I've cached the value and it was null in the database"? The answer is that you can't use "null" to mean both things, it's ambiguous.
@ForbesLindesay https://gist.github.com/ForbesLindesay/5392612#comment-816503 A new counter argument.
Excellent example, thanks @charleso .
@techtangents I don't get what you're not happy with, it's even mentioned as something you can do in the Fantasy Land Spec.
@Raynos just created https://gist.github.com/ForbesLindesay/5392701 I want to gather two separate gists and make each as strong as I can. I'll start incorporating other examples/counter arguments into each.
@techtangents I don't get what you're not happy with, it's even mentioned as something you can do in the Fantasy Land Spec.
I must have missed something. Is this a way to provide a map implementation for things that have either map, chain or then, as an interoperability thing?
Yep, it aims to implement map
for anything which has either map
, (chain
and of
) or (then
and of
but where then
behaves like chain
and only flattens one level).
P.S. if you put a new line after the quoted bit, it won't render the whole thing as a quote, it would also be helpful if you could go back and fix the formatting of a few past posts.
@Raynos I've attempted to incorporate your example into the gist so I've deleted your comment as I want to keep them both free of commentary. I've included your arguments (rephrased slightly) in https://gist.github.com/ForbesLindesay/5392701 There may be more to add, if so, please make suggestions in comments on that gist not the gist giving arguments against promises for promises.
How do people feel about my previously proposed suggestion for ultimately closing this issue. I feel the discussion has gone on too long with too much back and forth repetition in this issue to expect newcomers to catch up. This is why I want to start a fresh with just a summary of the arguments for and against that were discussed in this issue.
@ForbesLindesay: Sounds like a good proposal to me. I'm glad to hear about your moment of epiphany!
@ForbesLindesay what we really need is two new issues in the correct place. One with an amendum to .then()
to not recursively flatten. The other is an amendum to whatever to add .of()
(this probably requires speccing out the semantics of of()
in more detail).
I'm happy to see that issue for of
. I just think that, since we're very close to releasing a new promise spec that would forever make this a backwards incompatible change to the spec, we should focus on that for the time being.
If you ask for one, small change, and justify it, it's much more likely to get proper consideration than if you open lots of simultaneous issues asking to change everything. Lets first argue for the value behind only unwrapping a single layer, because if we have that, we can move forwards without breaking backwards compatibility. To this end, I have opened https://github.com/promises-aplus/promises-spec/issues/101 which I think should serve as the only place for discussion on this issue for the time being.
If we can agree there that we want promises for promises to be a possible thing, you're very unlikely to see any arguments regarding promise.of
being specc'd in a very simple, sane, way.
As an aside: http://www.techtangents.com/on-options-of-options/
Also, @ForbesLindesay, you said you didn't understand liftA2. I've tried to explain this in http://www.techtangents.com/explanation-of-lifta2-in-javascript/
There are lots of other tutorials on Functors, Applicatives and Monads out there. Most of them are in Haskell or Scala, though, not JavaScript. I would highly recommend you learn Haskell as it makes it easier to understand these concepts, so you can then apply them to your coding in other languages.
There's a ton of good information in this thread. Thanks, everyone.
I agree with @ForbesLindesay that it has reached the point where it's best to close and direct energy toward promises-aplus/promises-spec#101, specifically noting the process that has been set forth there.
@pufuwozu brought up a good point with his article
http://brianmckenna.org/blog/category_theory_promisesaplus
The notion of having a
point
function that takes a value and returns a promise would allow for writing powerful higher order functions.Basically prior art, a-la category theory shows that having a function that looks like point is a good thing, we should consider this.