"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loopUnit = exports.loop = void 0;
// ets_tracing: off
const Function_1 = require("../../Function");
const core_1 = require("../core");
const succeed_1 = require("../succeed");
const api_1 = require("./api");
const suspend_1 = require("./suspend");
/**
 * Loops with the specified effectual function, collecting the results into a
 * list. The moral equivalent of:
 *
 * ```
 * let s  = initial
 * let as = [] as readonly A[]
 *
 * while (cont(s)) {
 *   as = [body(s), ...as]
 *   s  = inc(s)
 * }
 *
 * A.reverse(as)
 * ```
 */
function loop(initial, cont, inc) {
    return (body, __trace) => (0, suspend_1.suspend)(() => {
        if (cont(initial)) {
            return (0, core_1.chain_)(body(initial), (a) => ((0, core_1.map)((as) => [a, ...as])(loop(inc(initial), cont, inc)(body))));
        }
        return (0, succeed_1.succeed)([]);
    }, __trace);
}
exports.loop = loop;
/**
 * Loops with the specified effectual function purely for its effects. The
 * moral equivalent of:
 *
 * ```
 * var s = initial
 *
 * while (cont(s)) {
 *   body(s)
 *   s = inc(s)
 * }
 * ```
 */
function loopUnit(initial, cont, inc) {
    return (body, __trace) => (0, suspend_1.suspend)(() => {
        if (cont(initial)) {
            return (0, core_1.chain_)(body(initial), () => loopUnit(inc(initial), cont, inc)(body));
        }
        return api_1.unit;
    }, __trace);
}
exports.loopUnit = loopUnit;
//# sourceMappingURL=loop.js.map