// ets_tracing: off import * as Cause from "../../../Cause/core.js" import * as E from "../../../Either/index.js" import { identity } from "../../../Function/index.js" import * as O from "../../../Option/index.js" import * as L from "../List/core.js" import * as Tp from "../Tuple/index.js" import type { ParSeq } from "./primitives.js" import * as P from "./primitives.js" /** * Returns the first event in this collection of events. If multiple events * occur in parallel and before any other events then any of these events * may be returned. */ export function first(self: ParSeq): O.Option { // eslint-disable-next-line no-constant-condition while (1) { switch (self._tag) { case "Single": { return O.some(self.a) } case "Empty": { return O.none } case "Both": { self = self.left break } case "Then": { self = self.left break } } } throw new Error("Bug") } function foldLoop( emptyCase: B, singleCase: (a: A) => B, thenCase: (l: B, r: B) => B, bothCase: (l: B, r: B) => B, inp: L.List>, out: L.List> ): L.List { // eslint-disable-next-line no-constant-condition while (1) { if (L.isEmpty(inp)) { return L.reduce_(out, L.empty(), (acc, val) => { if (val._tag === "Right") { return L.prepend_(acc, val.right) } else { if (val.left) { let parSeqs = acc const left = L.unsafeFirst(parSeqs) parSeqs = L.tail(parSeqs) const right = L.unsafeFirst(parSeqs) parSeqs = L.tail(parSeqs) return L.prepend_(parSeqs, bothCase(left!, right!)) } else { let parSeqs = acc const left = L.unsafeFirst(parSeqs) parSeqs = L.tail(parSeqs) const right = L.unsafeFirst(parSeqs) parSeqs = L.tail(parSeqs) return L.prepend_(parSeqs, thenCase(left!, right!)) } } }) } else { const head = L.unsafeFirst(inp)! const parSeqs = L.tail(inp) switch (head._tag) { case "Empty": { inp = parSeqs out = L.prepend_(out, E.right(emptyCase)) break } case "Single": { inp = parSeqs out = L.prepend_(out, E.right(singleCase(head.a))) break } case "Then": { inp = L.prepend_(L.prepend_(parSeqs, head.right), head.left) out = L.prepend_(out, E.left(false)) break } case "Both": { inp = L.prepend_(L.prepend_(parSeqs, head.right), head.left) out = L.prepend_(out, E.left(true)) break } } } } throw new Error("Bug") } /** * Folds over the events in this collection of events using the specified * functions. */ export function fold_( self: ParSeq, emptyCase: B, singleCase: (a: A) => B, thenCase: (l: B, r: B) => B, bothCase: (l: B, r: B) => B ): B { return L.unsafeFirst( foldLoop(emptyCase, singleCase, thenCase, bothCase, L.of(self), L.empty()) )! } /** * Folds over the events in this collection of events using the specified * functions. * * @ets_data_first fold_ */ export function fold( emptyCase: B, singleCase: (a: A) => B, thenCase: (l: B, r: B) => B, bothCase: (l: B, r: B) => B ): (self: ParSeq) => B { return (self) => fold_(self, emptyCase, singleCase, thenCase, bothCase) } /** * Constructs a new collection of events for each event in this collection of * events, collecting them back into a single collection of events. */ export function chain_(self: ParSeq, f: (a: A) => ParSeq): ParSeq { return fold_(self, P.empty as ParSeq, f, P.combineSeq_, P.combinePar_) } /** * Constructs a new collection of events for each event in this collection of * events, collecting them back into a single collection of events. * * @ets_data_first chain_ */ export function chain(f: (a: A) => ParSeq): (self: ParSeq) => ParSeq { return (self) => chain_(self, f) } /** * Flattens a collection of collections of events into a single collection * of events. */ export function flatten(self: ParSeq>) { return chain_(self, identity) } /** * Converts a ParSeq to a Cause */ export function toCause(self: ParSeq): Cause.Cause { return fold_( self, Cause.empty as Cause.Cause, Cause.fail, Cause.combineSeq, Cause.combinePar ) } /** * Transforms the type of events in this collection of events with the * specified function. */ export function map_(self: ParSeq, f: (a: A) => B): ParSeq { return chain_(self, (a) => P.single(f(a))) } /** * Transforms the type of events in this collection of events with the * specified function. * * @ets_data_first map_ */ export function map(f: (a: A) => B): (self: ParSeq) => ParSeq { return (self) => map_(self, f) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events using the specified function. */ export function zipWith_( self: ParSeq, that: ParSeq, f: (a: A, b: B) => C ): ParSeq { return chain_(self, (a) => map_(that, (b) => f(a, b))) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events using the specified function. * * @ets_data_first zipWith_ */ export function zipWith( that: ParSeq, f: (a: A, b: B) => C ): (self: ParSeq) => ParSeq { return (self) => zipWith_(self, that, f) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events, combining the elements into a * tuple. */ export function zip_(self: ParSeq, that: ParSeq): ParSeq> { return zipWith_(self, that, Tp.tuple) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events, combining the elements into a * tuple. * * @ets_data_first zip_ */ export function zip( that: ParSeq ): (self: ParSeq) => ParSeq> { return (self) => zip_(self, that) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events, keeping only the events from this * collection. */ export function zipLeft_(self: ParSeq, that: ParSeq): ParSeq { return zipWith_(self, that, (a, _b) => a) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events, keeping only the events from this * collection. * * @ets_data_first zipLeft_ */ export function zipLeft(that: ParSeq): (self: ParSeq) => ParSeq { return (self) => zipLeft_(self, that) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events, keeping only the events from that * collection. */ export function zipRight_(self: ParSeq, that: ParSeq): ParSeq { return zipWith_(self, that, (_a, b) => b) } /** * Combines this collection of events with that collection of events to * return the Cartesian product of events, keeping only the events from that * collection. * * @ets_data_first zipRight_ */ export function zipRight(that: ParSeq): (self: ParSeq) => ParSeq { return (self) => zipRight_(self, that) }