text: // Copyright (c) 2021, João Paulo Carreiro
  //
  // Permission to use, copy, modify, and/or distribute this software 
  // for any purpose with or without fee is hereby granted, provided 
  // that the above copyright notice and this permission notice appear 
  // in all copies.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 
  // WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 
  // WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 
  // THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 
  // CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
  // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 
  // NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 
  // WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
  'use strict'
  const prelude = require('../prelude')
  
  /**
   * Check if an object is a promise.
   * @param {*} obj The object to check.
   * @returns {boolean} True if object is a promise, false otherwise.
   */
  const isPromise = obj => Promise.resolve(obj) == obj
  
  /**
   * Run in order the list of promises and their arguments.
   * The items in the list are defined by the following object
   * {{ fun, args }}, where fun is the function (i.e.) promise
   * to execute and args is an array with the arguments.
   * @param {*} lst The list of promises to run.
   * @returns {array<*>} Am array with the result of each promise
   * in the list (ordered).
   */
  const sequence = lst => lst.reduce((accum, { fn, args }) => accum.then(out0 => _pFn(fn)(args).then(out1 => [...out0, out1])), Promise.resolve([]))
  
  /**
   * Run in order the list of promises and their arguments.
   * The items in the list are defined by the following object
   * {{ fun }}, where fun is the function (i.e. promise)
   * to execute. The output of one promise is then used as the
   * input to the next.
   * @param {*} lst The list of promises in the chain.
   * @param {*} val The initial value for the chain.
   * @returns {*} The output of the last promise in the chain
   * or the initial value if the chain is empty.
   */
  const chain = (lst, val) => lst.map(_fnM).reduce((accum, { fn }) => accum.then(output => _pFn(fn)(output)), Promise.resolve(val))
  
  const _pFn = fn => args => Promise.resolve(fn(...prelude.toArray(args)))
  
  const _fnM = fn => prelude.isFunction(fn) ? { fn } : fn
  
  /**
   * Execute a list of promises in parallel.     
   */
  const all = Promise.all
  
  /**
   * Race between a list of promises.
   */
  const race = Promise.race
  
  /**
   * A constant value as a promise.
   * @param {*} c The the constant value.
   * @return {Promise} The promise with the constant value resolved.
   */
  const constp = c => Promise.resolve(c)
  
  module.exports = {
      isPromise,
      sequence,
      chain,
      all,
      race,
      constp
  }
  
  
  
  
  