The Promise monad in JavaScript
To define a monad in JavaScript, we have to set two operators: bind
and unit
(in Haskell these two are >>=
and return
). Defining fail
will be useful too.
// unit :: a -> Promise a unit = x => new Promise(resolve => resolve(x)) // fail :: String -> Promise a fail = str => new Promise((resolve, reject) => reject(str)) // bind :: Promise a -> (a -> Promise b) -> Promise b bind = (p, np) => p.then(x => np(x), fail)
Let’s add also an operator for joining multiple operations into one:
// pipe :: [a -> Promise a] -> a -> Promise a pipe = ps => x => ps.reduce(bind, unit(x))
..and some definitions for testing:
// add10 :: Int -> Promise Int add10 = x => unit(x + 10) // add40 :: Int -> Promise Int add40 = pipe([add10, add10, add10, add10]) // fadd40 :: Int -> Promise Int fadd40 = pipe([add10, add10, _ => fail("oops"), add10])
And now we can test our Promise monad:
add40(8).then(x => console.log(x)) -------> 48 fadd40(8).then(x => console.log(x), err => console.log("err " + err)) -------> “err oops”
The above code was tested on Firefox.