Here is a translation of a modification of the example given in [1]:
const promise1 = Promise.resolve(123);
promise1.then(v => v * 2).then((value) => {
console.log(value);
// Expected output: 246
});
into Haskell: ghci> let promise1 :: IO Int = return 123
ghci> promise1 >>= (return . (* 2)) >>= print
246
One key discrepancy worth pointing out is that in the `Promise.then()` API of JavaScript, the function provided to `then` (e.g. `v => v * 2` above) is implicitly composed with a call to `::resolve` in order to turn that function's pure return value, the `Number` 246, into a Promise resolving into the `Number` 246; in Haskell, this operation must be made explicit (hence the composed function `return . (* 2)` passed to the first application of (>>=) or `bind`).You could say that the instance method `Promise.then()` expects an argument of type (a -> b), with the return value of type `b` being implicitly and automatically wrapped into a Monad `m b`, whereas Haskell's bind expects an argument of type (a -> m b) on that operator's right-hand side, with the return value explicitly wrapped into a Monad `m b` by the provided function argument itself.
[0] https://wiki.haskell.org/Monad
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
So in essence Promise.then() is like Array.map() while bind is like Array.flatMap()
Edit: It seems you are correct, you can indeed return a promise in the callback and it compose correctly. But in your example the callback does not return a promise and is therefore not an example of monadic bind.
The behavior of the returned promise (call it p) depends on the handler's
execution result, following a specific set of rules. If the handler function:
* returns a value: p gets fulfilled with the returned value as its value.
[...]
* returns an already fulfilled promise: p gets fulfilled with that promise's value as its value.
... then you can obtain a solution closer to the Haskell translation by using the behaviour of the second cited bullet point from the MDN article: const promise1 = Promise.resolve(123);
promise1.then(v => Promise.resolve(v * 2)).then((value) => {
console.log(value);
// Expected output: 246
});
[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...Callbacks are one particular monad, not monads in general: https://jsdw.me/posts/haskell-cont-monad/