import * as ROArray from "@fp-ts/data/ReadonlyArray"
import { identity } from "./Function.js"
import * as Option from "./Option.js"
import * as Dur from "@fp-ts/data/Duration"
export * from "@fp-ts/data/ReadonlyArray"
/**
* @tsplus getter ets/Ord toOrder
*/
export function convertOrd(_: Ord): Order {
return ({ compare: y => x => _.compare(x, y) })
}
/**
* @tsplus getter Generator toArray
* @tsplus getter Iterable toArray
*/
export function toArray(
gen: Generator
) {
return Array.from(gen)
}
/**
* Remove duplicates from an array, keeping the first occurrence of an element.
*
* @tsplus pipeable Array uniq
* @tsplus pipeable ReadonlyArray uniq
* @tsplus static fp-ts/data/ReadonlyArray.Ops uniq
*/
export function uniq(E: Equal) {
return (self: ReadonlyArray): ReadonlyArray => {
const includes = arrayIncludes(E)
const result: Array = []
const length = self.length
let i = 0
for (; i < length; i = i + 1) {
const a = self[i]!
if (!includes(result, a)) {
result.push(a)
}
}
return length === result.length ? self : result
}
}
function arrayIncludes(E: Equal) {
return (array: Array, value: A): boolean => {
for (let i = 0; i < array.length; i = i + 1) {
const element = array[i]!
if (E.equals(value, element)) {
return true
}
}
return false
}
}
/**
* @tsplus static fp-ts/data/Duration.Ops makeMillis
*/
export const millis_ = Dur.millis
export const { isArray } = Array
// export function deleteOrOriginal_(as: ReadonlyArray, a: A) {
// return as.remove(findIndexOrElse_(as, x => x === a))
// }
// export function deleteAtOrOriginal(i: number) {
// return (as: ReadonlyArray) => deleteAtOrOriginal_(as, i)
// }
// export function deleteOrOriginal(a: A) {
// return (as: ReadonlyArray) => deleteOrOriginal_(as, a)
// }
/**
* @tsplus static fp-ts/data/ReadonlyArray.Ops findFirstMap
* @tsplus static Array.Ops findFirstMap
* @tsplus pipeable Array findFirstMap
* @tsplus pipeable fp-ts/data/ReadonlyArray findFirstMap
* @tsplus pipeable ReadonlyArray findFirstMap
* @tsplus pipeable NonEmptyArray findFirstMap
* @tsplus pipeable NonEmptyArrayReadonlyArray findFirstMap
*/
export function findFirstMap(
f: (a: A) => Option.Option
) {
return (as: ReadonlyArray) => {
const len = as.length
for (let i = 0; i < len; i++) {
const v = f(as[i]!)
if (v.isSome()) {
return v
}
}
return Option.none
}
}
/**
* @tsplus static fp-ts/data/ReadonlyArray.NonEmptyArray.Ops fromArray
*/
export function NEAFromArray(ar: Array) {
return ar.length ? Option.some(ar as NonEmptyArray) : Option.none
}
/**
* @tsplus static fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray.Ops fromArray
*/
export function NEROArrayFromArray(ar: ReadonlyArray) {
return ar.length ? Option.some(ar as NonEmptyReadonlyArray) : Option.none
}
/**
* @tsplus pipeable Array sortWith
* @tsplus pipeable ReadonlyArray sortWith
*/
export function sortWith(
...ords: NonEmptyArguments>
): (a: ReadonlyArray) => ReadonlyArray {
return ROArray.sortBy(...ords.map(convertOrd))
}
/**
* @tsplus pipeable Array sortByO
* @tsplus pipeable ReadonlyArray sortByO
* @tsplus pipeable NonEmptyArray sortByO
* @tsplus pipeable NonEmptyArrayReadonlyArray sortByO
*/
export function sortByO(
ords: Option.Option>>
): (a: ReadonlyArray) => ReadonlyArray {
return ords.match(() => identity, _ => ROArray.sortBy(..._.map(convertOrd)))
}
/**
* @tsplus fluent ReadonlyArray groupByT
* @tsplus fluent Array groupByT
* @tsplus fluent NonEmptyArray groupByT
* @tsplus fluent NonEmptyArrayReadonlyArray groupByT
*/
export function groupByT(
as: ReadonlyArray,
f: (a: A) => Key
): ReadonlyArray]> {
const r: Record & { 0: A }> = {} as any
for (const a of as) {
const k = f(a)
// eslint-disable-next-line no-prototype-builtins
if (r.hasOwnProperty(k)) {
r[k]!.push(a)
} else {
r[k] = [a]
}
}
return Object.entries(r).map(([k, items]) => tuple(k as unknown as Key, items as NonEmptyReadonlyArray))
}
// /**
// * @tsplus fluent ReadonlyArray collect
// */
// export function arrayCollect(ar: readonly A[], collector: (a: A) => Option): readonly B[] {
// return Chunk.fromIterable(ar).filterMap(collector).toArray
// }
/**
* @tsplus operator ReadonlyArray &
* @tsplus fluent ReadonlyArray concat
*/
export function concat_(
self: ReadonlyArray,
that: ReadonlyArray
): ReadonlyArray {
return [...self, ...that]
}
/**
* Concatenates two ReadonlyArray together
*
* @tsplus operator ReadonlyArray +
*/
export const concatOperator: (
self: ReadonlyArray,
that: ReadonlyArray
) => ReadonlyArray = concat_
/**
* Prepends `a` to ReadonlyArray
*
* @tsplus operator ReadonlyArray + 1.0
*/
export function prependOperatorStrict(a: A, self: ReadonlyArray): ReadonlyArray {
return ROArray.prepend(a)(self)
}
/**
* Prepends `a` to ReadonlyArray
*
* @tsplus operator ReadonlyArray >
*/
export function prependOperator(a: A, self: ReadonlyArray): ReadonlyArray {
return prepend_(self, a)
}
/**
* Prepends `a` to ReadonlyArray
*
* @tsplus fluent ReadonlyArray prepend
*/
export function prepend_(tail: ReadonlyArray, head: B): ReadonlyArray {
const len = tail.length
const r = Array(len + 1)
for (let i = 0; i < len; i++) {
r[i + 1] = tail[i]
}
r[0] = head
return r as unknown as ReadonlyArray
}
/**
* Appends `a` to ReadonlyArray
*
* @tsplus fluent ReadonlyArray append
* @tsplus operator ReadonlyArray <
*/
export function append_(init: ReadonlyArray, end: B): ReadonlyArray {
const len = init.length
const r = Array(len + 1)
for (let i = 0; i < len; i++) {
r[i] = init[i]
}
r[len] = end
return r as unknown as ReadonlyArray
}
/**
* @tsplus operator ReadonlyArray + 1.0
*/
export const appendOperator: (self: ReadonlyArray, a: A) => ReadonlyArray = append_
/**
* @tsplus fluent ReadonlyArray randomElement 1
* @tsplus fluent Array randomElement 1
*/
export function randomElement(a: ReadonlyArray) {
return a[Math.floor(Math.random() * a.length)]
}
/**
* @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray randomElement 2
*/
export function randomElementNA(a: NonEmptyReadonlyArray): A {
return a[Math.floor(Math.random() * a.length)]
}
/**
* @tsplus pipeable Array mapNonEmpty
* @tsplus pipeable fp-ts/data/ReadonlyArray mapNonEmpty
* @tsplus pipeable fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray mapNonEmpty
* @tsplus pipeable fp-ts/data/ReadonlyArray.NonEmptyArray mapNonEmpty
*/
export const mapRA = ROArray.mapNonEmpty
/**
* @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray sortBy
*/
export function sortBy(na: NonEmptyReadonlyArray, ords: readonly Ord[]) {
return ROArray.sortBy(...ords.map(convertOrd))(na) as unknown as NonEmptyReadonlyArray
}
/**
* @tsplus static fp-ts/data/ReadonlyArray.Ops sortWithNonEmpty
* @tsplus pipeable ReadonlyArray sortWithNonEmpty
*/
export function sortWithNonEmpty(
...ords: NonEmptyArguments>
): (a: NonEmptyReadonlyArray) => NonEmptyArray {
return a => a.sortByNonEmpty(...ords.map(convertOrd))
}
/**
* @tsplus static fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray __call
*/
export const makeNA = ROArray.make
/**
* @tsplus fluent ReadonlyArray filterWith
*/
export function filterWith(self: ReadonlyArray, predicates: ReadonlyArray>) {
return self.filter(_ => predicates.every(f => f(_)))
}
/**
* Split the `items` array into multiple, smaller chunks of the given `size`.
*/
export function* _chunk_(items_: Iterable, size: number) {
const items = [...items_]
while (items.length) {
yield items.splice(0, size)
}
}
/**
* Split the `items` array into multiple, smaller chunks of the given `size`.
* @tsplus fluent Array chunk
* @tsplus fluent ReadonlyArray chunk
* @tsplus fluent fp-ts/data/Chunk chunk
* @tsplus fluent Iterable chunk
*/
export function chunk_(items_: Iterable, size: number) {
return Chunk.fromIterable(_chunk_(items_, size))
}
/**
* @tsplus getter Array toChunk
* @tsplus getter ReadonlyArray toChunk
* @tsplus getter Iterable toChunk
*/
export function toChunk(items: Iterable) {
return Chunk.fromIterable(items)
}
/**
* @tsplus getter ReadonlyArray toNonEmpty
* @tsplus getter Array toNonEmpty
* @tsplus getter fp-ts/data/ReadonlyArray toNonEmpty
*/
export const toNonEmptyArray = (a: ReadonlyArray) =>
a.length ? Option.some(a as NonEmptyReadonlyArray) : Option.none
/**
* @tsplus getter Iterable toArray
* @tsplus getter Iterator toArray
* @tsplus getter Generator toArray
*/
export const iterableToArray = Array.from
/**
* @tsplus getter Iterable toNonEmptyArray
*/
export function CollectionToNonEmptyReadonlyArray(c: Iterable) {
return iterableToArray(c).toNonEmpty
}
/**
* @tsplus getter fp-ts/data/Chunk toNonEmptyArray
*/
export function ChunkToNonEmptyReadonlyArray(c: Chunk) {
return c.toArray.toNonEmpty
}
/**
* @tsplus fluent Array forEachEffectPar
* @tsplus fluent ReadonlyArray forEachEffectPar
*/
export function ext_forEachEffectPar(
as: ReadonlyArray,
f: (a: A) => Effect
) {
return Effect.forEachPar(f)(as)
}
/**
* @tsplus fluent fp-ts/data/Chunk forEachEffectPar
*/
export function ext_CNKforEachEffectPar(
as: Chunk,
f: (a: A) => Effect
) {
return Effect.forEachPar(f)(as)
}
/**
* @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffectPar
*/
export function ext_NAforEachEffectPar(
as: NonEmptyReadonlyArray,
f: (a: A) => Effect
) {
return Effect.forEachPar(f)(as).map(_ => _.toNonEmptyArray.value!)
}
/**
* @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffect
*/
export function ext_NAforEach(as: NonEmptyReadonlyArray, f: (a: A) => Effect) {
return Effect.forEach(f)(as).map(_ => _.toNonEmptyArray.value!)
}
/**
* @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffectWithIndexPar
*/
export function ext_NAforEachEffectWithIndexPar(
as: NonEmptyReadonlyArray,
f: (a: A, i: number) => Effect
) {
return Effect.forEachParWithIndex(f)(as).map(_ => _.toNonEmptyArray.value!)
}
/**
* @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffectWithIndex
*/
export function ext_NAforEachWithIndex(
as: NonEmptyReadonlyArray,
f: (a: A, i: number) => Effect
) {
return Effect.forEachWithIndex(f)(as).map(_ => _.toNonEmptyArray.value!)
}
/**
* @tsplus fluent ReadonlyArray forEachEffectWithIndex
* @tsplus fluent Array forEachEffectWithIndex
* @tsplus fluent fp-ts/data/Chunk forEachEffectWithIndex
* @tsplus fluent ets/Set forEachEffectWithIndex
*/
export function ext_forEachWithIndex(as: Iterable, f: (a: A, i: number) => Effect) {
return Effect.forEachWithIndex(f)(as)
}
/**
* @tsplus fluent ReadonlyArray forEachEffectParWithIndex
* @tsplus fluent Array forEachEffectParWithIndex
* @tsplus fluent fp-ts/data/Chunk forEachEffectParWithIndex
* @tsplus fluent ets/Set forEachEffectParWithIndex
*/
export function ext_forEachParWithIndex(as: Iterable, f: (a: A, i: number) => Effect) {
return Effect.forEachParWithIndex(f)(as)
}
/**
* @tsplus getter Iterable toChunk
* @tsplus getter Iterator toChunk
* @tsplus getter Generator toChunk
*/
export const ext_itToChunk = Chunk.fromIterable