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

//https://medium.com/@dimpapadim3/async-functional-error-handling-9332dfe9f78c
//Copyright (c) 2019 dimitris papadimitriou

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

  const id = x => x;

  const EitherAsync = (actions, resolveMappings, rejectMappings) => ({

     map: (f) => EitherAsync(actions, compose(f, resolveMappings), rejectMappings),

     mapError: f => EitherAsync(actions, resolveMappings, compose(f, rejectMappings)),

     bimap: (f, g) => EitherAsync(actions, compose(f, resolveMappings), compose(g, rejectMappings)),

     ap: fv => EitherAsync((resolve, reject) => actions(f => fv.map(compose(f, resolveMappings)).cata({
        ok: resolve,
        error: reject
     }), reject), resolveMappings, rejectMappings),

     bind: f => EitherAsync((resolve, reject) => actions(x => f(resolveMappings(x)).cata({
        ok: resolve,
        error: reject
     }), reject), id, id),

     cata: alg => actions(compose(alg.ok, resolveMappings), compose(alg.error, rejectMappings)),

     toPromise: () => new Promise((resolve, reject) => actions(compose(resolve, resolveMappings), compose(reject, rejectMappings))),
     toEither: () => EitherAsync(actions, resolveMappings, rejectMappings),

  });

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

}())


  const ok = (v) => ({
    v: v,
    map: (f) => ok(f(v)), 
    cata: (alg) => alg.ok(v),  
  });
  
  const error = (v) => ({
    v: v,
    map: () => error(v), 
    cata: (alg) => alg.error(v),  
  });
 
  Promise.prototype.map = function(mapping) {
    var initialPromise = this;
    return new Promise(function(resolve) {
      initialPromise.then(result => resolve(mapping(result)))
    });
  }  
 
 
var getUser = () => fetch("https://api.github.com/users");

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

var toJson...