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.

Skomentuj

Leave a Reply

Your email address will not be published. Required fields are marked *