You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I want to start by saying that I mean in no way to invalidate your work. I think you're creating a nice, low barrier stepping stone from Promises to Monads, and I appreciate it (and thank you for mentioning Fluture).
However, I do feel that it's important to acknowledge (and be more explicit about in your readme) the fact that we cannot build a completely correct Applicative Functor on top of current implementations of Promises/A+ (except Creed*). I've also tried to highlight this in the second part of "Specialised API" in my Broken Promises article.
The missing piece we need to implement a correct Applicative Functor is "higher order Promises" or Promises of Promises. The problem is that when a Promise (as it is currently implemented) sees another Promise, it assimilates it and assumes its state, holding as its value the value of the other Promise, instead of holding the other Promise directly. You've come across this: your chain implementation is an exact copy of your map implementation.
constF=require('dashp')constg=x=>F.of(x+1)// :: Number -> Promise Numberconstf=F.chain(g)// :: Promise Number -> Promise Numberconsta=F.of(1)// :: Promise NumberF.map(x=>f(g(x)),a)// Promise { <resolved> 3 }// ≡F.map(f,F.map(g,a))// Promise { <rejected> TypeError: Future#chain expects its second argument to be a promise }
Furthermore, Fantasy Land specifies that "no parts of a should be checked", where a is the value passed to of(). Promises unfortunately do check a, and respond to whether it is a Promise or not (for assimilation).
In conclusion, I do see the value of a utility library that helps you think of Promises in algebraic terms, but I would really like to see the readme educating people (maybe just via a link to this issue) about how it fails to be algebraic due to the limitation imposed by Promises.
* An interesting thing to note is that these flaws are not inherent to Promises/A+. Automatic assimilation is just an implementation choice. Unfortunately, native Promises went with that choice. It is actually possible to implement Promises/A+ while retaining algebraic properties. The aforementioned Creed is one such implementation. Perhaps DashP could be a stepping stone from native Promises to Creed, for those who prefer eager execution semantics.
The text was updated successfully, but these errors were encountered:
Thanks so much for this comment. I was already wondering why chain and map are actually identical. Your explanations were very enlightening. Indeed, I don't attempt to build better Promises or such, I really just want to have a lightweight utility library that uses curried functions and that I can use with any existing Promise based code.
I really just want to have a lightweight utility library that uses curried functions and that I can use with any existing Promise based code.
Yeah, I definitely see it's use. I just didn't want any misconceptions to spread - your commit should be sufficient to avoid that. I'm very happy this has been enlightening! :)
I want to start by saying that I mean in no way to invalidate your work. I think you're creating a nice, low barrier stepping stone from Promises to Monads, and I appreciate it (and thank you for mentioning Fluture).
However, I do feel that it's important to acknowledge (and be more explicit about in your readme) the fact that we cannot build a completely correct Applicative Functor on top of current implementations of Promises/A+ (except Creed*). I've also tried to highlight this in the second part of "Specialised API" in my Broken Promises article.
The missing piece we need to implement a correct Applicative Functor is "higher order Promises" or Promises of Promises. The problem is that when a Promise (as it is currently implemented) sees another Promise, it assimilates it and assumes its state, holding as its value the value of the other Promise, instead of holding the other Promise directly. You've come across this: your
chain
implementation is an exact copy of yourmap
implementation.We can see this break the composition law:
Furthermore, Fantasy Land specifies that "no parts of
a
should be checked", wherea
is the value passed toof()
. Promises unfortunately do checka
, and respond to whether it is a Promise or not (for assimilation).We can see this break the homomorphism law:
In conclusion, I do see the value of a utility library that helps you think of Promises in algebraic terms, but I would really like to see the readme educating people (maybe just via a link to this issue) about how it fails to be algebraic due to the limitation imposed by Promises.
* An interesting thing to note is that these flaws are not inherent to Promises/A+. Automatic assimilation is just an implementation choice. Unfortunately, native Promises went with that choice. It is actually possible to implement Promises/A+ while retaining algebraic properties. The aforementioned Creed is one such implementation. Perhaps DashP could be a stepping stone from native Promises to Creed, for those who prefer eager execution semantics.
The text was updated successfully, but these errors were encountered: