// 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)
}