The main difference is that .bind()/.then() implicitly converts (a -> b) to (a -> M b) - i.e. if the function you pass to .bind()/.then() does not return a Promise/Monad as it should, it's converted. Promise.create() does something similar. This level of type-juggling is not weird for a dynamically-typed language.
So my question is: rather than attempting to define your own Monads that are more type-strict than the language itself, how many of the behaviours in this article can be implemented by extending Promise.prototype instead?
Promise.prototype.binary = function (right, binaryFn) {
return this.then(leftVal =>
Promise.resolve(right).then(rightVal =>
binaryFn(leftVal, rightVal)
)
);
};
onePromise.binary(twoPromise, (a, b) => a + b); // Adds two promises together