Promise Composition

https://github.com/eu81273/jsfiddle-console

by dimitrs_papadimitriou

HTML

<script src="https://rawgit.com/eu81273/jsfiddle-console/master/console.js"></script>
<script src="https://code.jquery.com/jquery-3.4.0.js"></script>

JavaScript

(function () {

    Promise.prototype.map = function (f) {
      return (self => new Promise(function (resolve) {
        self.then(result => resolve(f(result)))
      }))(this);
    }

    const compose = (...fns) => x => fns.reduceRight((y, f) => f(y), x);

    var id = x => x;

    var EitherAsync = (actions, fOk, fError) => ({
      map: f => EitherAsync(actions, compose(f, fOk), fError),
      mapError: f => EitherAsync(actions, fOk, compose(f, fError)),
      bimap: (f, g) => EitherAsync(actions, compose(f, fOk), compose(g, fError)),
      ap: fv => EitherAsync((resolve, reject) => actions(f => fv.map(compose(f, fOk)).cata({
        ok: resolve,
        error: reject
      }), reject), fOk, fError),

      bind: f => EitherAsync((resolve, reject) => actions(x => f(fOk(x)).cata({
        ok: resolve,
        error: reject
      }), reject), id, id),
      cata: alg => actions(compose(alg.ok, fOk), compose(alg.error, fError)),
    });

    Promise.prototype.toEither = function () {
      return EitherAsync((resolve, reject) => this.then(resolve).catch(reject), id, id);
    }

  }())
 
 







  var getUser = () => fetch("https://api.github.com/users");

  var getUserFollowers = (name) => fetch("https://api.github.com/users/" + name + "/followers");

  var toJson = response => response.json()

  getUser()
    .map(toJson)
    .toEither()
    .map(users => users[0].login)
    //.bind((v) => getUserFollowers(v).map(toJson).toEither())
  //  .map(followers => followers.map(follower => follower.login))
    .cata({
      ok: v => console.log(v),
      error: v => console.log("Error :" + v)
    });