# Are Promises Monads, Functor or Applicative

If we have ever programmed with JavaScript, we all know about Promises. The Promise object abstracts the future value of an asynchronous operation. It can be the eventual completion (or failure) of asynchronous result

Promises is very popular today. Many imperative programing languages adapt it. However, when we learn about functional programming, especially Haskell, sometimes we wonder that Promises are monads?

Haskell is near to mathematic. Each type class is a mathematic object. If we want to know a instance is a type of Functor, Monad or Applicative,we need to prove if the target is satisfy the laws.

Because each language has another mechanism to implement Promises, Promises can be different. In first section, I will talk about JavaScript.

## Laws

Before go to the detail, let's a look at those laws. Note, p ≡ q simply means that you can replace p with q and vice-versa, and the behavior of your program will not change: p and q are equivalent.

### Functor

`fmap id ≡ id -- Identity law`

fmap (g . f) ≡ fmap g . fmap f -- Associativity

### Monad

`return a >>= f ≡ f a -- Left identity`

m >>= return ≡ m -- Right identity

(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) -- Associativity

## JavaScript

### Are Promises Functor?

The analogous Promise function for `fmap`

is `then`

. The constructor is `Promise.resolve`

.

`// id :: a -> a`

const id = (a) => a

// fmap id ≡ id -- functor law

const lp = Promise.resolve(1).then(id)

const rp = id(Promise.resolve(1))

Promise.all([lp, rp]).then(([a, b]) => console.log(a === b))

// true

Promise seems satisfy Identity law. We can go next with Associativity law.

`// fmap (g . f) ≡ fmap g . fmap f -- Associativity`

const f = (a) => a * 2;

const g = (a) => a * 3;

Promise.all([

Promise.resolve(1).then(f).then(g),

Promise.resolve(1).then(a => g(f(a))),

]);

// true

Hooray. The result is same as the expectation. However:

`// fmap (g . f) ≡ fmap g . fmap f -- Associativity`

const f = (a) => Promise.resolve(a * 2);

const g = (pa) => pa.then((b) => b * 3);

Promise.resolve(1).then(f).then(g),

// TypeError: pa.then is not a function

If `f`

return a Promise, the law will be violated. The value that gets passed to f is implicitly unwrapped, causes TypeError

**Answer**: **No**

### Are Promises Monads?

The analogous Promise function for `bind`

is `then`

. It is same as `fmap`

, right? In my option, because JavaScript is dynamic language, to make developers easier to learn, and not confuse about result type, the internal async promises inside `then`

is implicitly unwrapped. The analogous function for `return`

is `Promise.resolve`

.

`// return a >>= f ≡ f a -- Left identity`

const f = (a) => Promise.resolve(a * 2);

const lp = Promise.resolve(1).then(f);

const rp = f(1)

Promise.all([lp, rp]).then(([a, b]) => console.log(a === b));

It upholds the law. However, if `a`

is a Promise, the law is violated.

`const f = (m) => m.then((a) => a * 2);`

Promise.resolve(Promise.resolve(1)).then(f).then(console.log);

// TypeError: m.then is not a function

Because Promise implicitly unwrapped the Promise inside, the value in `then`

is no longer Promise. The `TypeError`

is raised. Second:

`// m >>= return ≡ m -- Right identity`

Promise.all([

Promise.resolve(1).then((a) => Promise.resolve(a)),

Promise.resolve(1)

]).then(([a, b]) => console.log(a === b));

// true

Right identity is satisfied, too. Note, we can't use free point style `Promise.resolve(1).then(Promise.resolve)`

. `TypeError: PromiseResolve called on non-object`

will be raised.

Finally, the Associativity law:

//(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) -- Associativity

const f = x => Promise.resolve(x * 2);

const g = y => Promise.resolve(y * 3);

Promise.all([

Promise.resolve(1).then(f).then(g),

Promise.resolve(1).then((x) => f(x).then(g))

]).then(([a, b]) => console.log(a === b));

The law is satisfied. However, it is also violated if the input value is a Promise

//(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) -- Associativity

const a = Promise.resolve(1);

const f = p => p.then(x => x * 2);

const g = y => Promise.resolve(y * 3);

Promise.all([

Promise.resolve(a).then(f).then(g),

Promise.resolve(a).then((x) => f(x).then(g))

]).then(([a, b]) => console.log(a === b));

// TypeError: p.then is not a function

**Answer**: **No**

### So, how about Applicative?

Because Applicative class is extended from Functor class, so if Promises don't satisfy Functor class, Applicative don't satisfy too.

`class (Functor f) => Applicative f where`

pure :: a -> f a

(<*>) :: f (a -> b) -> f a -> f b

**Answer**: **No**

## Promises in Scala

In Scala, the author divide this asynchronous specification into 2 terms: `Future`

and `Promise`

, and we usually call it `Future`

. In brief:

A future is a placeholder object for a result that does not yet exist. A promise is a writable, single-assignment container, which completes a future. Promises can complete the future with a result to indicate success, or with an exception to indicate failure. Futures and Promises

Scala language is a combination of OOP and common function programming with static types. Of course it is much better than JavaScript too. With `map`

and `flatMap`

, it remove the confusion of JavaScript Promise

`val fa = Future { 1 }`

fa map { a => a * 2 }

// scala.concurrent.Future[Int]

fa map { a => Future { a * 2 } }

// scala.concurrent.Future[scala.concurrent.Future[Int]]

fa flatMap { a => Future { a * 2 } }

// scala.concurrent.Future[Int]

**Answer**: **Yes All**

## References

- Futures and Promises - Kisalaya Prasad, Avanti Patil, and Heather Miller
- Monad Laws
- Functor
- Applicative Functors