//#region src/internal/types.d.ts
/** @internal */
type MaybePromiseLike<Value> = Value | PromiseLike<Value>;

/** @internal */
type StrictNegative<Numeric extends number> = Numeric extends 0 ? never : `${Numeric}` extends `-${string}` ? Numeric : never;

/** @internal */

/** @internal */
type NonNegative<Numeric extends number> = Numeric extends 0 ? Numeric : StrictNegative<Numeric> extends never ? Numeric : never;

/** @internal */
type StrictInteger<Numeric extends number> = `${Numeric}` extends `${bigint}` ? Numeric : never;

/** @internal */
type CheckNumericLiteral<Numeric extends number, LiteralNumber extends number> = number extends Numeric ? Numeric : LiteralNumber;

/** @internal */
type Integer<Numeric extends number> = CheckNumericLiteral<Numeric, StrictInteger<Numeric>>;

/** @internal */
type NonNegativeInteger<Numeric extends number> = CheckNumericLiteral<Numeric, NonNegative<StrictInteger<Numeric>>>;

/** @internal */
type PositiveInteger<Numeric extends number> = CheckNumericLiteral<Numeric, NonNegative<StrictInteger<Numeric>>>;
//#endregion
//#region src/operations/core.d.ts
/** @internal */
type Curried<Parameters extends readonly any[], Return> = <PartialParameters extends Partial<Parameters>>(...args: PartialParameters) => PartialParameters extends Parameters ? Return : Parameters extends readonly [...TupleOfSameLength<PartialParameters>, ...infer RemainingParameters] ? RemainingParameters extends any[] ? Curried<RemainingParameters, Return> : never : never;

/** @internal */
type TupleOfSameLength<Tuple extends readonly any[]> = Extract<{ [Key in keyof Tuple]: any }, readonly any[]>;

/**
 * Returns a [curried](https://lfi.dev/docs/concepts/currying) version of `fn`.
 *
 * @example
 * ```js playground
 * import { curry } from 'lfi'
 *
 * function slothLog(a, b, c) {
 *   console.log(`${a} Sloth ${b} Sloth ${c}`)
 * }
 *
 * const curriedSlothLog = curry(slothLog)
 *
 * console.log(curriedSlothLog.name)
 * //=> slothLog
 *
 * console.log(curriedSlothLog.length)
 * //=> 3
 *
 * curriedSlothLog(`Hello`, `World`, `!`)
 * curriedSlothLog(`Hello`)(`World`, `!`)
 * curriedSlothLog(`Hello`, `World`)(`!`)
 * curriedSlothLog(`Hello`)(`World`)(`!`)
 * //=> Hello Sloth World Sloth !
 * //=> Hello Sloth World Sloth !
 * //=> Hello Sloth World Sloth !
 * //=> Hello Sloth World Sloth !
 * ```
 *
 * @category Core
 * @since v0.0.1
 */
declare const curry: <Parameters extends readonly any[], Return>(fn: (...args: Parameters) => Return) => Curried<Parameters, Return>;

/**
 * Returns the result of piping `value` through the given functions.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => word.toUpperCase()),
 *     reduce(toArray()),
 *     // Also works with non-`lfi` functions!
 *     array => array.sort(),
 *   ),
 * )
 * //=> [ 'SLOTH', 'LAZY', 'SLEEP' ]
 * ```
 *
 * @category Core
 * @since v0.0.1
 */
declare const pipe: {
  <Value>(value: Value): Value;
  <A, B>(value: A, fn: (a: A) => B): B;
  <A, B, C>(value: A, fn1: (a: A) => B, fn2: (b: B) => C): C;
  <A, B, C, D>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): D;
  <A, B, C, D, E>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E): E;
  <A, B, C, D, E, F>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F): F;
  <A, B, C, D, E, F, G>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G): G;
  <A, B, C, D, E, F, G, H>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H): H;
  <A, B, C, D, E, F, G, H, I>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I): I;
  <A, B, C, D, E, F, G, H, I, J>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I, fn9: (i: I) => J): J;
  (value: unknown, ...fns: ((value: unknown) => unknown)[]): unknown;
};

/**
 * Returns a function that takes a single parameter and pipes it through the
 * given functions.
 *
 * @example
 * ```js playground
 * import { compose, map, reduce, toArray } from 'lfi'
 *
 * const screamify = compose(
 *   map(word => word.toUpperCase()),
 *   reduce(toArray()),
 *   // Also works with non-`lfi` functions!
 *   array => array.sort(),
 * )
 *
 * console.log(screamify([`sloth`, `lazy`, `sleep`]))
 * //=> [ 'SLOTH', 'LAZY', 'SLEEP' ]
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
declare const compose: {
  (): <Value>(value: Value) => Value;
  <A, B>(fn: (a: A) => B): (value: A) => B;
  <A, B, C>(fn1: (a: A) => B, fn2: (b: B) => C): (value: A) => C;
  <A, B, C, D>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): (value: A) => D;
  <A, B, C, D, E>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E): (value: A) => E;
  <A, B, C, D, E, F>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F): (value: A) => F;
  <A, B, C, D, E, F, G>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G): (value: A) => G;
  <A, B, C, D, E, F, G, H>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H): (value: A) => H;
  <A, B, C, D, E, F, G, H, I>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I): (value: A) => I;
  <A, B, C, D, E, F, G, H, I, J>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I, fn9: (i: I) => J): (value: A) => J;
  (...fns: ((value: unknown) => unknown)[]): (value: unknown) => unknown;
};

/**
 * Returns an async iterable wrapper around `iterable`.
 *
 * WARNING: When passing a concur iterable the default behavior of the returned
 * async iterable is to buffer the values yielded by the concur iterable if they
 * are not read from the async iterable as quickly as they are yielded by the
 * concur iterable. This happens because
 * [concur iterables are push-based while async iterables are pull-based](https://lfi.dev/docs/concepts/concurrent-iterable#how-is-it-different-from-an-asynciterable),
 * which creates backpressure. To customize how backpressure is applied, pass a
 * {@link BackpressureStrategy}.
 *
 * @example
 * ```js playground
 * import { asAsync } from 'lfi'
 *
 * const asyncIterable = asAsync([`sloth`, `lazy`, `sleep`])
 *
 * console.log(typeof asyncIterable[Symbol.asyncIterator])
 * //=> function
 *
 * for await (const value of asyncIterable) {
 *   console.log(value)
 * }
 * //=> sloth
 * //=> lazy
 * //=> sleep
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
declare const asAsync: {
  <Value>(iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>): AsyncIterable<Awaited<Value>>;
  <Value, Size extends number = number>(concurIterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>, options?: AsAsyncOptions<Size>): AsyncIterable<Awaited<Value>>;
};

/**
 * Options for {@link asAsync}.
 *
 * @category Core
 * @since v5.0.0
 */
type AsAsyncOptions<Size extends number = number> = Readonly<{
  /**
   * The strategy to use for applying backpressure when the input concur
   * iterable is yielding values faster than the returned async iterable can
   * process them.
   *
   * Does nothing if the input is not a concur iterable.
   *
   * @since v2.0.0
   */
  backpressureStrategy?: BackpressureStrategy<Size>;
}>;

/**
 * A strategy to use for applying backpressure adapting a concur iterable from
 * push-based iteration to pull-based iteration.
 *
 * @category Core
 * @since v5.0.0
 */
type BackpressureStrategy<Size extends number = number> = Readonly<{
  /**
   * The maximum number of values to buffer when the concur iterable yields
   * values faster than the downstream consumer can process them.
   *
   * Defaults to `Infinity`.
   */
  bufferLimit?: PositiveInteger<Size>;

  /**
   * The strategy to apply when the {@link BackpressureStrategy.bufferLimit}
   * would be exceeded.
   *
   * The strategies behave as follows:
   * - `drop-first`: When the buffer is full, earlier buffered values are
   *   evicted to make room for new ones.
   * - `drop-last`: When the buffer is full, new values are ignored.
   * - `error`: When the buffer is full and a new value comes in, an error is
   *   thrown.
   *
   * Defaults to `error`. Note that `overflowStrategy` does nothing when
   * {@link BackpressureStrategy.bufferLimit} is `Infinity`.
   */
  overflowStrategy?: `drop-first` | `drop-last` | `error`;
}>;

/**
 * A symbol used as the key when storing a {@link ConcurIterable}'s iteration
 * function.
 *
 * @category Core
 * @since v5.0.0
 */
declare const concurIteratorSymbol: unique symbol;

/**
 * Represents a lazy collection of values, each of type `Value`, that can be
 * iterated concurrently.
 *
 * The collection can be iterated by invoking the concur iterable's
 * {@link concurIteratorSymbol} function with an `apply` callback. The callback
 * is applied to each value in the collection, potentially asynchronously, in
 * some order.
 *
 * Invoking the concur iterable's {@link concurIteratorSymbol} function returns
 * a promise that resolves when `apply` has been applied to each value in the
 * concur iterable and each result returned by `apply` is awaited.
 *
 * A [concur iterable](https://lfi.dev/docs/concepts/concurrent-iterable) is
 * effectively a cold push-based observable backed by some asynchronous
 * operations.
 *
 * @example
 * ```js playground
 * import { asConcur, concurIteratorSymbol, mapConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const concurIterable = pipe(
 *   asConcur([`sloth`, `lazy`, `sleep`]),
 *   mapConcur(async word => {
 *     const response = await fetch(`${API_URL}/${word}`)
 *     return (await response.json())[0].phonetic
 *   }),
 * )
 *
 * await concurIterable[concurIteratorSymbol](console.log)
 * // NOTE: This order may change between runs
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
type ConcurIterable<Value> = {
  [concurIteratorSymbol]: (apply: ConcurIterableApply<Value>) => Promise<void>;
};

/**
 * The callback invoked for each value of a {@link ConcurIterable}.
 *
 * @category Core
 * @since v2.0.0
 */
type ConcurIterableApply<Value> = (value: Value) => MaybePromiseLike<void>;

/**
 * Returns a concur iterable wrapper around `iterable`.
 *
 * @example
 * ```js playground
 * import { asConcur, forEachConcur } from 'lfi'
 *
 * const concurIterable = asConcur([`sloth`, `lazy`, `sleep`])
 *
 * await forEachConcur(console.log, concurIterable)
 * //=> sloth
 * //=> lazy
 * //=> sleep
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
declare const asConcur: <Value>(iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>) => ConcurIterable<Awaited<Value>>;

/**
 * An iterable that contains zero values.
 *
 * Can be used as an iterable of any type.
 *
 * Like `[]`, but opaque.
 *
 * @example
 * ```js playground
 * import { empty } from 'lfi'
 *
 * console.log([...empty()])
 * //=> []
 * ```
 *
 * @category Core
 * @since v0.0.1
 */
declare const empty: <Value = unknown>() => Iterable<Value>;

/**
 * An async iterable that contains zero values.
 *
 * Can be used as an async iterable of any type.
 *
 * Like `[]`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { emptyAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * console.log(
 *   await pipe(
 *     emptyAsync(),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> []
 * ```
 *
 * @category Core
 * @since v0.0.1
 */
declare const emptyAsync: <Value = unknown>() => AsyncIterable<Value>;

/**
 * A concur iterable that contains zero values.
 *
 * Can be used as a concur iterable of any type.
 *
 * Like `[]`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { emptyConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * console.log(
 *   await pipe(
 *     emptyConcur(),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> []
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
declare const emptyConcur: <Value = unknown>() => ConcurIterable<Value>;

/**
 * Returns an iterable equivalent, but not referentially equal, to `iterable`.
 *
 * @example
 * ```js playground
 * import { opaque } from 'lfi'
 *
 * const array = [`sloth`, `lazy`, `sleep`]
 * const iterable = opaque(array)
 *
 * console.log(array === iterable)
 * //=> false
 *
 * console.log([...iterable])
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Core
 * @since v2.0.0
 */
declare const opaque: <Value>(iterable: Iterable<Value>) => Iterable<Value>;

/**
 * Returns an async iterable equivalent, but not referentially equal, to
 * `asyncIterable`.
 *
 * @example
 * ```js playground
 * import { asAsync, opaqueAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const asyncIterable = asAsync([`sloth`, `lazy`, `sleep`])
 * asyncIterable.property = 42
 * const opaqueAsyncIterable = opaqueAsync(asyncIterable)
 *
 * console.log(asyncIterable === opaqueAsyncIterable)
 * //=> false
 *
 * console.log(opaqueAsyncIterable.property)
 * //=> undefined
 *
 * console.log(
 *   await pipe(
 *     opaqueAsyncIterable,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Core
 * @since v2.0.0
 */
declare const opaqueAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;

/**
 * Returns an concur iterable equivalent, but not referentially equal, to
 * `concurIterable`.
 *
 * @example
 * ```js playground
 * import { asConcur, opaqueConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const concurIterable = asConcur([`sloth`, `lazy`, `sleep`])
 * concurIterable.property = 42
 * const opaqueConcurIterable = opaqueConcur(concurIterable)
 *
 * console.log(concurIterable === opaqueConcurIterable)
 * //=> false
 *
 * console.log(opaqueConcurIterable.property)
 * //=> undefined
 *
 * console.log(
 *   await pipe(
 *     opaqueConcurIterable,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Core
 * @since v2.0.0
 */
declare const opaqueConcur: <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
//#endregion
//#region src/operations/optionals.d.ts
/**
 * An iterable containing exactly zero or one values.
 *
 * @category Optionals
 * @since v2.0.0
 */
type Optional<Value> = Iterable<Value>;

/**
 * An async iterable containing exactly zero or one values.
 *
 * @category Optionals
 * @since v2.0.0
 */
type AsyncOptional<Value> = AsyncIterable<Value>;

/**
 * A concur iterable containing exactly zero or one values.
 *
 * @category Optionals
 * @since v2.0.0
 */
type ConcurOptional<Value> = ConcurIterable<Value>;

/**
 * Returns the only value in `iterable` if it contains exactly one value.
 * Otherwise, returns the result of invoking `fn`.
 *
 * @example
 * ```js playground
 * import { or, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`],
 *     or(() => `never called`),
 *   ),
 * )
 * //=> sloth
 *
 * console.log(
 *   pipe(
 *     [],
 *     or(() => `called!`),
 *   ),
 * )
 * //=> called!
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     or(() => `called!`),
 *   ),
 * )
 * //=> called!
 * ```
 *
 * @category Optionals
 * @since v0.0.1
 */
declare const or: {
  <Value>(fn: () => Value): (iterable: Iterable<Value>) => Value;
  <Value>(fn: () => Value, iterable: Iterable<Value>): Value;
};

/**
 * Returns a promise that resolves to the only value in `asyncIterable` if it
 * contains exactly one value. Otherwise, returns a promise that resolves to
 * the awaited result of invoking `fn`.
 *
 * @example
 * ```js playground
 * import { asAsync, findAsync, orAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const findWordWithPartOfSpeech = partOfSpeech =>
 *   pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     findAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech)
 *     }),
 *     orAsync(() => `no ${partOfSpeech}???`),
 *   )
 *
 * console.log(await findWordWithPartOfSpeech(`noun`))
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`verb`))
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`adjective`))
 * //=> lazy
 * console.log(await findWordWithPartOfSpeech(`adverb`))
 * //=> no adverb???
 * ```
 *
 * @category Optionals
 * @since v0.0.1
 */
declare const orAsync: {
  <Value>(fn: () => MaybePromiseLike<Value>): (asyncIterable: AsyncIterable<Value>) => Promise<Value>;
  <Value>(fn: () => MaybePromiseLike<Value>, asyncIterable: AsyncIterable<Value>): Promise<Value>;
};

/**
 * Returns a promise that resolves to the only value in `concurIterable` if it
 * contains exactly one value. Otherwise, returns a promise that resolves to
 * the awaited result of invoking `fn`.
 *
 * The promise only rejects if `fn` throws or rejects. It does not reject if the
 * given `concurIterable` rejects. Instead this function excludes erroring
 * values when counting the number of values in `concurIterable`.
 *
 * @example
 * ```js playground
 * import { asConcur, findConcur, orConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const findWordWithPartOfSpeech = partOfSpeech =>
 *   pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     findConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech)
 *     }),
 *     orConcur(() => `no ${partOfSpeech}???`),
 *   )
 *
 * console.log(await findWordWithPartOfSpeech(`noun`))
 * // NOTE: This word may change between runs
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`verb`))
 * // NOTE: This word may change between runs
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`adjective`))
 * //=> lazy
 * console.log(await findWordWithPartOfSpeech(`adverb`))
 * //=> no adverb???
 * ```
 *
 * @category Optionals
 * @since v0.0.2
 */
declare const orConcur: {
  <Value>(fn: () => MaybePromiseLike<Value>): (concurIterable: ConcurIterable<Value>) => Promise<Value>;
  <Value>(fn: () => MaybePromiseLike<Value>, concurIterable: ConcurIterable<Value>): Promise<Value>;
};

/**
 * Returns the only value in `iterable` if it contains exactly one value.
 * Otherwise, throws an error.
 *
 * @example
 * ```js playground
 * import { get } from 'lfi'
 *
 * console.log(get([`sloth`]))
 * //=> sloth
 *
 * try {
 *   console.log(get([]))
 * } catch {
 *   console.log(`Oh no! It was empty...`)
 * }
 * //=> Oh no! It was empty...
 *
 * try {
 *   console.log(get([`sloth`, `lazy`, `sleep`]))
 * } catch {
 *   console.log(`Oh no! It had more than one value...`)
 * }
 * //=> Oh no! It had more than one value...
 * ```
 *
 * @category Optionals
 * @since v0.0.1
 */
declare const get: <Value>(iterable: Iterable<Value>) => Value;

/**
 * Returns a promise that resolves to the only value in `asyncIterable` if it
 * contains exactly one value. Otherwise, returns a promise that rejects.
 *
 * @example
 * ```js playground
 * import { asAsync, findAsync, getAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const findWordWithPartOfSpeech = partOfSpeech =>
 *   pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     findAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech)
 *     }),
 *     getAsync,
 *   )
 *
 * console.log(await findWordWithPartOfSpeech(`noun`))
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`verb`))
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`adjective`))
 * //=> lazy
 * try {
 *   console.log(await findWordWithPartOfSpeech(`adverb`))
 * } catch {
 *   console.log(`Oh no! It was empty...`)
 * }
 * //=> Oh no! It was empty...
 * ```
 *
 * @category Optionals
 * @since v0.0.1
 */
declare const getAsync: <Value>(asyncIterable: AsyncIterable<Value>) => Promise<Value>;

/**
 * Returns a promise that resolves to the only value in `concurIterable` if it
 * contains exactly one value. Otherwise, returns a promise that rejects.
 *
 * The promise does not necessarily reject if the given `concurIterable`
 * rejects. Instead this function excludes erroring values when counting the
 * number of values in `concurIterable`.
 *
 * @example
 * ```js playground
 * import { asConcur, findConcur, getConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const findWordWithPartOfSpeech = partOfSpeech =>
 *   pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     findConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech)
 *     }),
 *     getConcur,
 *   )
 *
 * console.log(await findWordWithPartOfSpeech(`noun`))
 * // NOTE: This word may change between runs
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`verb`))
 * // NOTE: This word may change between runs
 * //=> sloth
 * console.log(await findWordWithPartOfSpeech(`adjective`))
 * //=> lazy
 * try {
 *   console.log(await findWordWithPartOfSpeech(`adverb`))
 * } catch {
 *   console.log(`Oh no! It was empty...`)
 * }
 * //=> Oh no! It was empty...
 * ```
 *
 * @category Optionals
 * @since v0.0.2
 */
declare const getConcur: <Value>(concurIterable: ConcurIterable<Value>) => Promise<Value>;

/**
 * Returns a pair of iterables. If `iterable` is empty, then both of the
 * returned iterables are empty. Otherwise, the first iterable contains the
 * first value of `iterable` and the second iterable contains the rest of the
 * values of `iterable`. The second iterable can only be iterated once.
 *
 * @example
 * ```js playground
 * import { count, get, next } from 'lfi'
 *
 * const [first, rest] = next([`sloth`, `lazy`, `sleep`])
 *
 * console.log(get(first))
 * //=> sloth
 *
 * console.log([...rest])
 * //=> [ 'lazy', 'sleep' ]
 *
 * const [first2, rest2] = next([])
 *
 * console.log(count(first2))
 * //=> 0
 *
 * console.log(count(rest2))
 * //=> 0
 * ```
 *
 * @category Optionals
 * @since v0.0.1
 */
declare const next: <Value>(iterable: Iterable<Value>) => [Optional<Value>, Iterable<Value>];

/**
 * Returns a promise that resolves to a pair of async iterables. If
 * `asyncIterable` is empty, then both of the returned async iterables are
 * empty. Otherwise, the first async iterable contains the first value of
 * `asyncIterable` and the second async iterable contains the rest of the values
 * of `asyncIterable`. The second async iterable can only be iterated once.
 *
 * @example
 * ```js playground
 * import { asAsync, countAsync, emptyAsync, getAsync, mapAsync, nextAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const [first, rest] = await pipe(
 *   asAsync([`sloth`, `lazy`, `sleep`]),
 *   mapAsync(async word => {
 *     const response = await fetch(`${API_URL}/${word}`)
 *     return (await response.json())[0].phonetic
 *   }),
 *   nextAsync,
 * )
 *
 * console.log(await getAsync(first))
 * //=> /slɑθ/
 *
 * console.log(
 *   await pipe(
 *     rest,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ '/ˈleɪzi/', '/sliːp/' ]
 *
 * const [first2, rest2] = await nextAsync(emptyAsync)
 *
 * console.log(await countAsync(first2))
 * //=> 0
 *
 * console.log(await countAsync(rest2))
 * //=> 0
 * ```
 *
 * @category Optionals
 * @since v0.0.1
 */
declare const nextAsync: <Value>(asyncIterable: AsyncIterable<Value>) => Promise<[AsyncOptional<Value>, AsyncIterable<Value>]>;
//#endregion
//#region src/operations/reducers.d.ts
/**
 * A reducer that reduces by combining pairs of values using function
 * application.
 *
 * @example
 * ```js playground
 * import { or, pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4],
 *     reduce(
 *       // This is a `FunctionReducer`
 *       (number1, number2) => number1 + number2,
 *     ),
 *     or(() => 0),
 *   ),
 * )
 * //=> 10
 * ```
 *
 * @category Reducers
 * @since v2.0.0
 */
type FunctionReducer<Value = unknown> = (acc: Value, value: Value) => Value;

/**
 * A reducer that reduces by combining pairs of values using
 * {@link RawOptionalReducerWithoutFinish.add}.
 *
 * @example
 * ```js playground
 * import { or, pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4],
 *     reduce(
 *       // This is a `RawOptionalReducerWithoutFinish`
 *       {
 *         add: (number1, number2) => number1 + number2,
 *       },
 *     ),
 *     or(() => 0),
 *   ),
 * )
 * //=> 10
 * ```
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawOptionalReducerWithoutFinish<Value = unknown, This = unknown> = {
  add: (this: This, acc: Value, value: Value) => Value;
};

/**
 * A reducer that reduces by combining pairs of values using
 * {@link RawOptionalReducerWithoutFinish.add} and then transforming the final
 * value using {@link RawOptionalReducerWithFinish.finish}.
 *
 * @example
 * ```js playground
 * import { or, pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4],
 *     reduce(
 *       // This is a `RawOptionalReducerWithFinish`
 *       {
 *         add: (number1, number2) => number1 + number2,
 *         finish: sum => `The sum is ${sum}`,
 *       },
 *     ),
 *     or(() => `There are no numbers`),
 *   ),
 * )
 * //=> The sum is 10
 * ```
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawOptionalReducerWithFinish<Value = unknown, Finished = Value, This = unknown> = RawOptionalReducerWithoutFinish<Value, This> & {
  finish: (this: This, acc: Value) => Finished;
};

/**
 * A reducer that reduces by combining pairs of values using
 * {@link RawOptionalReducerWithoutFinish.add} and then transforming the final
 * value using {@link RawOptionalReducerWithFinish.finish}.
 *
 * It's identical to {@link RawOptionalReducerWithFinish} except its `this` is
 * bound by {@link normalizeReducer}.
 *
 * @example
 * ```js playground
 * import { or, pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4],
 *     reduce(
 *       // This will be an `OptionalReducer` once it's normalized by `reduce`
 *       {
 *         add: (number1, number2) => number1 + number2,
 *         finish: sum => `The sum is ${sum}`,
 *       },
 *     ),
 *     or(() => `There are no numbers`),
 *   ),
 * )
 * //=> The sum is 10
 * ```
 *
 * @category Reducers
 * @since v2.0.0
 */
type OptionalReducer<Value = unknown, Finished = Value> = RawOptionalReducerWithFinish<Value, Finished>;

/**
 * A reducer that reduces by creating an initial accumulator using
 * {@link RawReducerWithoutFinish.create} and then adding values to the
 * accumulator values using {@link RawReducerWithoutFinish.add}.
 *
 * @example
 * ```js playground
 * import { pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4],
 *     reduce(
 *       // This is a `RawReducerWithoutFinish`
 *       {
 *         create: () => 0,
 *         add: (number1, number2) => number1 + number2,
 *       },
 *     ),
 *   ),
 * )
 * //=> 10
 * ```
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawReducerWithoutFinish<Value = unknown, Acc = Value, This = unknown> = {
  create: (this: This) => Acc;
  add: (this: This, acc: Acc, value: Value) => Acc;
};

/**
 * A reducer that reduces by creating an initial accumulator using
 * {@link RawReducerWithoutFinish.create}, then adding values to the accumulator
 * values using {@link RawReducerWithoutFinish.add}, and then transforming the
 * final accumulator using {@link RawReducerWithFinish.finish}.
 *
 * @example
 * ```js playground
 * import { pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4],
 *     reduce(
 *       // This is a `RawReducerWithFinish`
 *       {
 *         create: () => 0,
 *         add: (number1, number2) => number1 + number2,
 *         finish: sum => `The sum is ${sum}`,
 *       },
 *     ),
 *   ),
 * )
 * //=> The sum is 10
 * ```
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawReducerWithFinish<Value = unknown, Acc = Value, Finished = Acc, This = unknown> = RawReducerWithoutFinish<Value, Acc, This> & {
  finish: (this: This, acc: Acc) => Finished;
};

/**
 * A reducer that reduces by creating an initial accumulator using
 * {@link RawReducerWithoutFinish.create}, then adding values to the accumulator
 * values using {@link RawReducerWithoutFinish.add}, and then transforming the
 * final accumulator using {@link RawReducerWithFinish.finish}.
 *
 * It's identical to {@link RawReducerWithFinish} except its `this` is bound by
 * {@link normalizeReducer}.
 *
 * @example
 * ```js playground
 * import { pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4],
 *     reduce(
 *       // This will be a `Reducer` once it's normalized by `reduce`
 *       {
 *         create: () => 0,
 *         add: (number1, number2) => number1 + number2,
 *         finish: sum => `The sum is ${sum}`,
 *       },
 *     ),
 *   ),
 * )
 * //=> The sum is 10
 * ```
 *
 * @category Reducers
 * @since v2.0.0
 */
type Reducer<Value = unknown, Acc = Value, Finished = Acc> = RawReducerWithFinish<Value, Acc, Finished>;

/**
 * A keyed reducer that reduces by creating an initial accumulator using
 * {@link RawReducerWithoutFinish.create} and then adding key-value pairs to the
 * accumulator values using {@link RawReducerWithoutFinish.add}. The accumulator can be
 * queried for values by key using {@link RawKeyedReducer.get}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawKeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value], This = unknown> = RawReducerWithoutFinish<readonly [Key, Value], Acc, This> & {
  get: (this: This, acc: Acc, key: Key) => Value | typeof NO_ENTRY;
};

/**
 * A keyed reducer that reduces by creating an initial accumulator using
 * {@link RawReducerWithoutFinish.create} and then adding key-value pairs to the
 * accumulator values using {@link RawReducerWithoutFinish.add}. The accumulator
 * can be queried for values by key using {@link RawKeyedReducer.get}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type KeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value]> = RawKeyedReducer<Key, Value, Acc>;

/**
 * An async reducer that reduces by combining pairs of values using function
 * application.
 *
 * @category Reducers
 * @since v2.0.0
 */
type AsyncFunctionReducer<Value = unknown> = (acc: Value, value: Value) => MaybePromiseLike<Value>;

/**
 * An async reducer that reduces by combining pairs of values using
 * {@link RawAsyncOptionalReducerWithoutFinish.add}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawAsyncOptionalReducerWithoutFinish<Value = unknown, This = unknown> = {
  add: (this: This, acc: Value, value: Value) => MaybePromiseLike<Value>;
};

/**
 * An async reducer that reduces by combining pairs of values using
 * {@link RawAsyncOptionalReducerWithoutFinish.add} and then transforming the
 * final value using {@link RawAsyncOptionalReducerWithFinish.finish}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawAsyncOptionalReducerWithFinish<Value = unknown, Finished = Value, This = unknown> = RawAsyncOptionalReducerWithoutFinish<Value, This> & {
  finish: (this: This, acc: Value) => MaybePromiseLike<Finished>;
};

/**
 * An async reducer that reduces by combining pairs of values using
 * {@link RawAsyncOptionalReducerWithoutFinish.add} and then transforming the
 * final value using {@link RawAsyncOptionalReducerWithFinish.finish}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type AsyncOptionalReducer<Value = unknown, Finished = Value> = RawAsyncOptionalReducerWithFinish<Value, Finished>;

/**
 * An async reducer that reduces by creating an initial accumulator using
 * {@link RawAsyncReducerWithoutFinish.create} and then adding values to the
 * accumulator values using {@link RawAsyncReducerWithoutFinish.add}. The async
 * reducer is optionally able to combine pairs of accumulators using
 * {@link RawAsyncReducerWithoutFinish.combine}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawAsyncReducerWithoutFinish<Value = unknown, Acc = Value, This = unknown> = {
  create: (this: This) => MaybePromiseLike<Acc>;
  add: (this: This, acc: Acc, value: Value) => MaybePromiseLike<Acc>;
  combine?: (this: This, acc1: Acc, acc2: Acc) => MaybePromiseLike<Acc>;
};

/**
 * An async reducer that reduces by creating an initial accumulator using
 * {@link RawAsyncReducerWithoutFinish.create}, then adding values to the
 * accumulator values using {@link RawAsyncReducerWithoutFinish.add}, and then
 * transforming the final accumulator using
 * {@link RawAsyncReducerWithFinish.finish}. The async
 * reducer is optionally able to combine pairs of accumulators using
 * {@link RawAsyncReducerWithoutFinish.combine}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawAsyncReducerWithFinish<Value = unknown, Acc = Value, Finished = Acc, This = unknown> = RawAsyncReducerWithoutFinish<Value, Acc, This> & {
  finish: (this: This, acc: Acc) => MaybePromiseLike<Finished>;
};

/**
 * An async reducer that reduces by creating an initial accumulator using
 * {@link RawAsyncReducerWithoutFinish.create}, then adding values to the
 * accumulator values using {@link RawAsyncReducerWithoutFinish.add}, and then
 * transforming the final accumulator using
 * {@link RawAsyncReducerWithFinish.finish}. The async reducer is optionally
 * able to combine pairs of accumulators using
 * {@link RawAsyncReducerWithoutFinish.combine}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type AsyncReducer<Value = unknown, Acc = Value, Finished = Acc> = RawAsyncReducerWithFinish<Value, Acc, Finished>;

/**
 * An async keyed reducer that reduces by creating an initial accumulator using
 * {@link RawAsyncReducerWithoutFinish.create} and then adding key-value pairs
 * to the accumulator values using {@link RawAsyncReducerWithoutFinish.add}. The
 * async keyed reducer is optionally able to combine pairs of accumulators using
 * {@link RawAsyncReducerWithoutFinish.combine}. The accumulator can be queried
 * for values by key using {@link RawAsyncKeyedReducer.get}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type RawAsyncKeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value], This = unknown> = RawAsyncReducerWithoutFinish<readonly [Key, Value], Acc, This> & {
  get: (this: This, acc: Acc, key: Key) => MaybePromiseLike<Value | typeof NO_ENTRY>;
};

/**
 * An async keyed reducer that reduces by creating an initial accumulator using
 * {@link RawAsyncReducerWithoutFinish.create} and then adding key-value pairs
 * to the accumulator values using {@link RawAsyncReducerWithoutFinish.add}. The
 * async keyed reducer is optionally able to combine pairs of accumulators using
 * {@link RawAsyncReducerWithoutFinish.combine}. The accumulator can be queried
 * for values by key using {@link RawAsyncKeyedReducer.get}.
 *
 * @category Reducers
 * @since v2.0.0
 */
type AsyncKeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value]> = RawAsyncKeyedReducer<Key, Value, Acc>;

/**
 * A unique value representing the lack of an entry for some key in a
 * {@link KeyedReducer} or {@link AsyncKeyedReducer}.
 *
 * Keyed reducers use this instead of `null` or `undefined` because they are
 * valid values. Furthermore, introducing a `has` method for the purpose of
 * disambiguation would be less performant due to the need to perform the lookup
 * twice when the entry exists: `has` followed by `get` for the same key.
 *
 * @category Reducers
 * @since v2.0.0
 */
declare const NO_ENTRY: unique symbol;

/**
 * Returns a {@link Reducer} or {@link OptionalReducer} equivalent to `reducer`
 * except its final value is transformed using `fn`.
 *
 * @category Reducers
 * @since v2.0.0
 */
declare const mapReducer: {
  <Value, Acc, From, To, This>(fn: (value: From) => To, reducer: Readonly<RawReducerWithFinish<Value, Acc, From, This>>): Reducer<Value, Acc, To>;
  <From, To>(fn: (value: From) => To): <Value, Acc, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, From, This>>) => Reducer<Value, Acc, To>;
  <Value, From, To, This>(fn: (value: From) => To, reducer: Readonly<RawReducerWithoutFinish<Value, From, This>>): Reducer<Value, To>;
  <From, To>(fn: (value: From) => To): <Value, This>(reducer: Readonly<RawReducerWithoutFinish<Value, From, This>>) => Reducer<Value, To>;
  <Value, From, To, This>(fn: (value: From) => To, reducer: Readonly<RawOptionalReducerWithFinish<Value, From, This>>): OptionalReducer<Value, To>;
  <From, To>(fn: (value: From) => To): <Value, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, From, This>>) => OptionalReducer<Value, To>;
  <From, To, This>(fn: (value: From) => To, reducer: Readonly<RawOptionalReducerWithoutFinish<From, This>>): OptionalReducer<To>;
  <From, To>(fn: (value: From) => To): <This>(reducer: Readonly<RawOptionalReducerWithoutFinish<From, This>>) => OptionalReducer<To>;
  <From, To>(fn: (value: From) => To, reducer: FunctionReducer<From>): OptionalReducer<To>;
  <From, To>(fn: (value: From) => To): (reducer: FunctionReducer<From>) => OptionalReducer<To>;
};

/**
 * Returns an {@link AsyncReducer} equivalent to `reducer` except its final
 * value is transformed using `fn`.
 *
 * @category Reducers
 * @since v2.0.0
 */
declare const mapAsyncReducer: {
  <Value, Acc, From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, From, This>>): AsyncReducer<Value, Acc, To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>): <Value, Acc, This>(asyncReducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, From, This>>) => AsyncReducer<Value, Acc, To>;
  <Value, From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncReducerWithoutFinish<Value, From, This>>): AsyncReducer<Value, To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>): <Value, This>(asyncReducer: Readonly<RawAsyncReducerWithoutFinish<Value, From, This>>) => AsyncReducer<Value, To>;
  <Value, From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncOptionalReducerWithFinish<Value, From, This>>): AsyncOptionalReducer<Value, To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>): <Value, This>(asyncReducer: Readonly<RawAsyncOptionalReducerWithFinish<Value, From, This>>) => AsyncOptionalReducer<Value, To>;
  <From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncOptionalReducerWithoutFinish<From, This>>): AsyncOptionalReducer<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>): <This>(asyncReducer: Readonly<RawAsyncOptionalReducerWithoutFinish<From, This>>) => AsyncOptionalReducer<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: AsyncFunctionReducer<From>): AsyncOptionalReducer<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>): (asyncReducer: AsyncFunctionReducer<From>) => AsyncOptionalReducer<To>;
};

/**
 * Returns a non-raw version of `reducer`.
 *
 * @category Reducers
 * @since v2.0.0
 */
declare const normalizeReducer: {
  <Key, Value, Acc, This>(reducer: Readonly<RawKeyedReducer<Key, Value, Acc, This>>): KeyedReducer<Key, Value, Acc>;
  <Value, Acc, Finished, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>): Reducer<Value, Acc, Finished>;
  <Value, Acc, This>(reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>): Reducer<Value, Acc>;
  <Value, Finished, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>): OptionalReducer<Value, Finished>;
  <Value, This>(reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>): OptionalReducer<Value>;
  <Value>(reducer: FunctionReducer<Value>): OptionalReducer<Value>;
  <Key, Value, Acc, This>(reducer: Readonly<RawAsyncKeyedReducer<Key, Value, Acc, This>>): AsyncKeyedReducer<Key, Value, Acc>;
  <Value, Acc, Finished, This>(reducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, Finished, This>>): AsyncReducer<Value, Acc, Finished>;
  <Value, Acc, This>(reducer: Readonly<RawAsyncReducerWithoutFinish<Value, Acc, This>>): AsyncReducer<Value, Acc>;
  <Value, Finished, This>(reducer: Readonly<RawAsyncOptionalReducerWithFinish<Value, Finished, This>>): AsyncOptionalReducer<Value, Finished>;
  <Value, This>(reducer: Readonly<RawAsyncOptionalReducerWithoutFinish<Value, This>>): AsyncOptionalReducer<Value>;
  <Value>(reducer: AsyncFunctionReducer<Value>): AsyncOptionalReducer<Value>;
};

/**
 * Returns the result of reducing `iterable` using `reducer`.
 *
 * An initial accumulator is created using
 * {@link RawReducerWithoutFinish.create}. Then each value in `iterable` is
 * added to the accumulator and the current accumulator is updated using
 * {@link RawReducerWithoutFinish.add}. Finally, the resulting accumulator is
 * transformed using {@link RawReducerWithFinish.finish} if specified.
 *
 * If `reducer` is an optional reducer (no
 * {@link RawReducerWithoutFinish.create} method), then an empty iterable is
 * returned if `iterable` is empty. Otherwise, an iterable containing the result
 * of reducing using the first value of the iterable as the initial accumulator
 * is returned.
 *
 * Like `Array.prototype.reduce`, but for iterables.
 *
 * @example
 * ```js playground
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     map(string => string.length),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 5, 10, 15 ]
 * ```
 *
 * @category Reducers
 * @since v0.0.1
 */
declare const reduce: {
  <Value, Acc, Finished, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>, iterable: Iterable<Value>): Finished;
  <Value, Acc, Finished, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>): (iterable: Iterable<Value>) => Finished;
  <Value, Acc, This>(reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>, iterable: Iterable<Value>): Acc;
  <Value, Acc, This>(reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>): (iterable: Iterable<Value>) => Acc;
  <Value, Finished, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>, iterable: Iterable<Value>): Optional<Finished>;
  <Value, Finished, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>): (iterable: Iterable<Value>) => Optional<Finished>;
  <Value, This>(reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>, iterable: Iterable<Value>): Optional<Value>;
  <Value, This>(reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>): (iterable: Iterable<Value>) => Optional<Value>;
  <Value>(reducer: FunctionReducer<Value>, iterable: Iterable<Value>): Optional<Value>;
  <Value>(reducer: FunctionReducer<Value>): (iterable: Iterable<Value>) => Optional<Value>;
};

/**
 * Returns the result of reducing the `asyncIterable` using `asyncReducer`.
 *
 * Informally, an initial accumulator is created using
 * {@link RawAsyncReducerWithoutFinish.create}. Then each value in
 * `asyncIterable` is added to the accumulator and the current accumulator is
 * updated using {@link RawAsyncReducerWithoutFinish.add}. Finally, the
 * resulting accumulator is transformed using
 * {@link RawAsyncReducerWithFinish.finish} if specified. Multiple accumulators
 * may be created, added to, and then combined if supported via
 * {@link RawAsyncReducerWithoutFinish.combine} and the next value of
 * `asyncIterable` is ready before promises from
 * {@link RawAsyncReducerWithoutFinish.add} resolve.
 *
 * If `asyncReducer` is an async optional reducer (no
 * {@link RawAsyncReducerWithoutFinish.create} method), then an empty async
 * iterable is returned if `asyncIterable` is empty. Otherwise, an async
 * iterable containing the result of reducing using the first value of the async
 * iterable as the initial accumulator is returned.
 *
 * Like `Array.prototype.reduce`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, mapAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 * await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Reducers
 * @since v0.0.1
 */
declare const reduceAsync: {
  <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>, asyncIterable: AsyncIterable<Value>): Promise<Finished>;
  <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>): (asyncIterable: AsyncIterable<Value>) => Promise<Finished>;
  <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>, asyncIterable: AsyncIterable<Value>): Promise<Acc>;
  <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>): (asyncIterable: AsyncIterable<Value>) => Promise<Acc>;
  <Value, Finished, This>(asyncReducer: RawAsyncOptionalReducerWithFinish<Value, Finished, This> | RawOptionalReducerWithFinish<Value, Finished, This>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Finished>;
  <Value, Finished, This>(asyncReducer: RawAsyncOptionalReducerWithFinish<Value, Finished, This> | RawOptionalReducerWithFinish<Value, Finished, This>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Finished>;
  <Value, This>(asyncReducer: RawAsyncOptionalReducerWithoutFinish<Value, This> | RawOptionalReducerWithoutFinish<Value, This>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>;
  <Value, This>(asyncReducer: RawAsyncOptionalReducerWithoutFinish<Value, This> | RawOptionalReducerWithoutFinish<Value, This>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;
  <Value>(asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>;
  <Value>(asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;
};

/**
 * Returns the result of reducing the `concurIterable` using `asyncReducer`.
 *
 * The resulting promise or concur iterable rejects if `concurIterable` rejects.
 *
 * Informally, an initial accumulator is created using
 * {@link RawAsyncReducerWithoutFinish.create}. Then each value in
 * `concurIterable` is added to the accumulator and the current accumulator is
 * updated using {@link RawAsyncReducerWithoutFinish.add}. Finally, the
 * resulting accumulator is transformed using
 * {@link RawAsyncReducerWithFinish.finish} if specified. Multiple accumulators
 * may be created, added to, and then combined if supported via
 * {@link RawAsyncReducerWithoutFinish.combine} and the next value of
 * `concurIterable` is ready before promises from
 * {@link RawAsyncReducerWithoutFinish.add} resolve.
 *
 * If `asyncReducer` is an async optional reducer (no
 * {@link RawAsyncReducerWithoutFinish.create} method), then an empty concur
 * iterable is returned if `concurIterable` is empty. Otherwise, an concur
 * iterable containing the result of reducing using the first value of the
 * concur iterable as the initial accumulator is returned.
 *
 * Like `Array.prototype.reduce`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { asConcur, mapConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Reducers
 * @since v0.0.1
 */
declare const reduceConcur: {
  <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>, concurIterable: ConcurIterable<Value>): Promise<Finished>;
  <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>): (concurIterable: ConcurIterable<Value>) => Promise<Finished>;
  <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>, concurIterable: ConcurIterable<Value>): Promise<Acc>;
  <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>): (concurIterable: ConcurIterable<Value>) => Promise<Acc>;
  <Value, Finished, This>(asyncReducer: RawAsyncOptionalReducerWithFinish<Value, Finished, This> | RawOptionalReducerWithFinish<Value, Finished, This>, concurIterable: ConcurIterable<Value>): ConcurOptional<Finished>;
  <Value, Finished, This>(asyncReducer: RawAsyncOptionalReducerWithFinish<Value, Finished, This> | RawOptionalReducerWithFinish<Value, Finished, This>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Finished>;
  <Value, This>(asyncReducer: RawAsyncOptionalReducerWithoutFinish<Value, This> | RawOptionalReducerWithoutFinish<Value, This>, concurIterable: ConcurIterable<Value>): ConcurOptional<Value>;
  <Value, This>(asyncReducer: RawAsyncOptionalReducerWithoutFinish<Value, This> | RawOptionalReducerWithoutFinish<Value, This>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;
  <Value>(asyncReducer: FunctionReducer<Value> | AsyncFunctionReducer<Value>, concurIterable: ConcurIterable<Value>): ConcurOptional<Value>;
  <Value>(asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;
};
//#endregion
//#region src/operations/collections.d.ts
/**
 * Returns a {@link Reducer} that collects values to an `Array`.
 *
 * @example
 * ```js playground
 * import { cycle, pipe, reduce, take, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `lazy`, `sleep`]),
 *     take(4),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep', 'sloth' ]
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const toArray: <Value>() => Reducer<Value, Value[]>;

/**
 * Returns a {@link Reducer} that collects values to a `Set`.
 *
 * @example
 * ```js playground
 * import { cycle, pipe, reduce, take, toSet } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `lazy`, `sleep`]),
 *     take(4),
 *     reduce(toSet()),
 *   ),
 * )
 * //=> Set(3) {
 * //=>   'sloth',
 * //=>   'lazy',
 * //=>   'sleep'
 * //=> }
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const toSet: <Value>() => Reducer<Value, Set<Value>>;

/**
 * Returns a {@link Reducer} that collects objects to a `WeakSet`.
 *
 * @example
 * ```js playground
 * import { cycle, map, pipe, reduce, take, toWeakSet } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `lazy`, `sleep`]),
 *     take(4),
 *     map(word => ({ sloth: word })),
 *     reduce(toWeakSet()),
 *   ),
 * )
 * //=> WeakSet { <items unknown> }
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const toWeakSet: <Value extends object>() => Reducer<Value, WeakSet<Value>>;

/**
 * Returns a {@link KeyedReducer} that collects key-value pairs to an object.
 *
 * In the case of pairs with duplicate keys, the value of the last one wins.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toObject } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => [word, word.length]),
 *     reduce(toObject()),
 *   ),
 * )
 * //=> {
 * //=>   sloth: 5,
 * //=>   lazy: 4,
 * //=>   sleep: 5
 * //=> }
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const toObject: <Key extends PropertyKey, Value>() => RawKeyedReducer<Key, Value, Record<Key, Value>>;

/**
 * Returns a {@link KeyedReducer} that collects key-value pairs to a `Map`.
 *
 * In the case of pairs with duplicate keys, the value of the last one wins.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toMap } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => [word, word.length]),
 *     reduce(toMap()),
 *   ),
 * )
 * //=> Map(3) {
 * //=>   'sloth' => 5,
 * //=>   'lazy' => 4,
 * //=>   'sleep' => 5
 * //=> }
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const toMap: <Key, Value>() => RawKeyedReducer<Key, Value, Map<Key, Value>>;

/**
 * Returns a {@link KeyedReducer} that collects key-value pairs to a `WeakMap`.
 *
 * In the case of pairs with duplicate keys, the value of the last one wins.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toWeakMap } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => [{ sloth: word }, word.length]),
 *     reduce(toWeakMap()),
 *   ),
 * )
 * //=> WeakMap { <items unknown> }
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const toWeakMap: <Key extends object, Value>() => RawKeyedReducer<Key, Value, WeakMap<Key, Value>>;

/**
 * Returns a {@link Reducer} that reduces key-value pairs using `outerReducer`
 * and reduces values with the same key using `innerReducer`.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toArray, toGrouped, toMap } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => [word.length, word]),
 *     reduce(toGrouped(toArray(), toMap())),
 *   ),
 * )
 * //=> Map(2) {
 * //=>   5 => [ 'sloth', 'sleep' ],
 * //=>   4 => [ 'lazy' ]
 * //=> }
 * ```
 *
 * @category Collections
 * @since v2.0.0
 */
declare const toGrouped: {
  <Key, Value, InnerAcc, InnerFinished, InnerThis, OuterAcc, OuterThis>(innerReducer: Readonly<RawReducerWithFinish<Value, InnerAcc, InnerFinished, InnerThis>>, outerReducer: Readonly<RawKeyedReducer<Key, InnerAcc | InnerFinished, OuterAcc, OuterThis>>): Reducer<readonly [Key, Value], never, OuterAcc>;
  <Value, InnerAcc, InnerFinished, InnerThis>(innerReducer: Readonly<RawReducerWithFinish<Value, InnerAcc, InnerFinished, InnerThis>>): <Key, OuterAcc, OuterThis>(outerReducer: Readonly<RawKeyedReducer<Key, InnerAcc | InnerFinished, OuterAcc, OuterThis>>) => Reducer<readonly [Key, Value], never, OuterAcc>;
  <Key, Value, InnerAcc, InnerThis, OuterAcc, OuterThis>(innerReducer: Readonly<RawReducerWithoutFinish<Value, InnerAcc, InnerThis>>, outerReducer: Readonly<RawKeyedReducer<Key, InnerAcc, OuterAcc, OuterThis>>): Reducer<readonly [Key, Value], never, OuterAcc>;
  <Value, InnerAcc, InnerThis>(innerReducer: Readonly<RawReducerWithoutFinish<Value, InnerAcc, InnerThis>>): <Key, OuterAcc, OuterThis>(outerReducer: Readonly<RawKeyedReducer<Key, InnerAcc, OuterAcc, OuterThis>>) => Reducer<readonly [Key, Value], never, OuterAcc>;
  <Key, Value, InnerFinished, InnerThis, OuterAcc, OuterThis>(innerReducer: Readonly<RawOptionalReducerWithFinish<Value, InnerFinished, InnerThis>>, outerReducer: Readonly<RawKeyedReducer<Key, Value | InnerFinished, OuterAcc, OuterThis>>): Reducer<readonly [Key, Value], never, OuterAcc>;
  <Value, InnerFinished, InnerThis>(innerReducer: Readonly<RawOptionalReducerWithFinish<Value, InnerFinished, InnerThis>>): <Key, OuterAcc, OuterThis>(outerReducer: Readonly<RawKeyedReducer<Key, Value | InnerFinished, OuterAcc, OuterThis>>) => Reducer<readonly [Key, Value], never, OuterAcc>;
  <Key, Value, InnerThis, OuterAcc, OuterThis>(innerReducer: Readonly<RawOptionalReducerWithoutFinish<Value, InnerThis>>, outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>): Reducer<readonly [Key, Value], never, OuterAcc>;
  <Value, InnerThis>(innerReducer: Readonly<RawOptionalReducerWithoutFinish<Value, InnerThis>>): <Key, OuterAcc, OuterThis>(outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>) => Reducer<readonly [Key, Value], never, OuterAcc>;
  <Key, Value, OuterAcc, OuterThis>(innerReducer: FunctionReducer<Value>, outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>): Reducer<readonly [Key, Value], never, OuterAcc>;
  <Value>(innerReducer: FunctionReducer<Value>): <Key, OuterAcc, OuterThis>(outerReducer: Readonly<RawKeyedReducer<Key, Value, OuterAcc, OuterThis>>) => Reducer<readonly [Key, Value], never, OuterAcc>;
};

/**
 * Returns a {@link Reducer} or {@link OptionalReducer} that reduces values to
 * an object or array of the same shape as `reducers` using all of the reducers
 * in `reducers`.
 *
 * Returns an {@link OptionalReducer} if at least one of the input reducers is
 * an {@link OptionalReducer}. Otherwise, returns a {@link Reducer}.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toCount, toJoin, toMultiple, toSet } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => word.length),
 *     reduce(toMultiple([toSet(), toCount(), toJoin(`,`)])),
 *   ),
 * )
 * //=> [
 * //=>   Set(2) { 5, 4 },
 * //=>   3,
 * //=>   '5,4,5'
 * //=> ]
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => word.length),
 *     reduce(
 *       toMultiple({
 *         set: toSet(),
 *         count: toCount(),
 *         string: toJoin(`,`),
 *       }),
 *     ),
 *   ),
 * )
 * //=> {
 * //=>   set: Set(2) { 5, 4 },
 * //=>   count: 3,
 * //=>   string: '5,4,5'
 * //=> }
 * ```
 *
 * @category Collections
 * @since v2.0.0
 */
declare const toMultiple: {
  <Value, Reducers extends readonly [RawReducerWithoutFinish<Value, any>] | readonly RawReducerWithoutFinish<Value, any>[] | Readonly<Record<PropertyKey, RawReducerWithoutFinish<Value, any>>>>(reducers: Reducers): Reducer<Value, { -readonly [Key in keyof Reducers]: Reducers[Key] extends RawReducerWithoutFinish<Value, infer Acc> ? Acc : never }, { -readonly [Key in keyof Reducers]: Reducers[Key] extends RawReducerWithFinish<Value, any, infer Finished> ? Finished : Reducers[Key] extends RawReducerWithoutFinish<Value, infer Acc> ? Acc : never }>;
  <Value, Reducers extends readonly [RawReducerWithoutFinish<Value, any> | RawOptionalReducerWithoutFinish<Value> | FunctionReducer<Value>] | readonly (RawReducerWithoutFinish<Value, any> | RawOptionalReducerWithoutFinish<Value> | FunctionReducer<Value>)[] | Readonly<Record<PropertyKey, RawReducerWithoutFinish<Value, any> | RawOptionalReducerWithoutFinish<Value> | FunctionReducer<Value>>>>(reducers: Reducers): OptionalReducer<Value, { -readonly [Key in keyof Reducers]: Reducers[Key] extends RawReducerWithFinish<Value, any, infer Finished> ? Finished : Reducers[Key] extends RawOptionalReducerWithFinish<Value, infer Finished> ? Finished : Value }>;
};

/**
 * Returns a {@link Reducer} that concatenates values to a string where values
 * are separated by `separator`.
 *
 * Joins like `Array.prototype.join`, but does not treat `null`, `undefined`,
 * or `[]` specially.
 *
 * Use when composing reducers. Prefer {@link join}, {@link joinAsync}, and
 * {@link joinConcur} for direct use on iterables.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toGrouped, toJoin, toMap } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => [word.length, word]),
 *     reduce(toGrouped(toJoin(`,`), toMap())),
 *   ),
 * )
 * //=> Map(2) {
 * //=>   5 => 'sloth,sleep',
 * //=>   4 => 'lazy'
 * //=> }
 * ```
 *
 * @category Collections
 * @since v2.0.0
 */
declare const toJoin: (separator: string) => Reducer<unknown, unknown, string>;

/**
 * Returns the string concatenation of the values of `iterable`, separated by
 * `separator`.
 *
 * Like `Array.prototype.join`, but for iterables, except it does not treat
 * `null`, `undefined`, or `[]` specially.
 *
 * @example
 * ```js playground
 * import { join, map, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => word.toUpperCase()),
 *     join(`, `),
 *   ),
 * )
 * //=> SLOTH, LAZY, SLEEP
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const join: {
  (separator: string): (iterable: Iterable<unknown>) => string;
  (separator: string, iterable: Iterable<unknown>): string;
};

/**
 * Returns a promise that resolves to the string concatenation of the values of
 * `asyncIterable`, separated by `separator`.
 *
 * Like `Array.prototype.join`, but for async iterables, except it does not
 * treat `null`, `undefined`, or `[]` specially.
 *
 * @example
 * ```js playground
 * import { asAsync, joinAsync, mapAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     joinAsync(`, `),
 *   ),
 * )
 * //=> /slɑθ/, /ˈleɪzi/, /sliːp/
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const joinAsync: {
  (separator: string): (asyncIterable: AsyncIterable<unknown>) => Promise<string>;
  (separator: string, asyncIterable: AsyncIterable<unknown>): Promise<string>;
};

/**
 * Returns a promise that resolves to the string concatenation of the values of
 * `concurIterable`, separated by `separator`.
 *
 * The promise rejects if the given `concurIterable` rejects.
 *
 * Like `Array.prototype.join`, but for concur iterables, except it does not
 * treat `null`, `undefined`, or `[]` specially.
 *
 * WARNING: The iteration order of concur iterables is not deterministic, so the
 * values will be concatenated in an arbitrary order.
 *
 * @example
 * ```js playground
 * import { asConcur, joinConcur, mapConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     joinConcur(`, `),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> /slɑθ/, /ˈleɪzi/, /sliːp/
 * ```
 *
 * @category Collections
 * @since v0.0.2
 */
declare const joinConcur: {
  (separator: string): (concurIterable: ConcurIterable<unknown>) => Promise<string>;
  (separator: string, concurIterable: ConcurIterable<unknown>): Promise<string>;
};
//#endregion
//#region src/operations/filters.d.ts
/**
 * Returns an iterable that contains the values of `iterable` in iteration order
 * excluding the values for which `fn` returns a falsy value.
 *
 * Like `Array.prototype.filter`, but for iterables.
 *
 * @example
 * ```js playground
 * import { filter, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     filter(word => word.startsWith(`s`)),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'sleep' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const filter: {
  <From, To extends From>(fn: (value: From) => value is To): (iterable: Iterable<From>) => Iterable<To>;
  <From, To extends From>(fn: (value: From) => value is To, iterable: Iterable<From>): Iterable<To>;
  <Value>(fn: (value: Value) => unknown): (iterable: Iterable<Value>) => Iterable<Value>;
  <Value>(fn: (value: Value) => unknown, iterable: Iterable<Value>): Iterable<Value>;
};

/**
 * Returns an async iterable that contains the values of `asyncIterable` in
 * iteration order excluding the values for which `fn` returns a value awaitable
 * to a falsy value.
 *
 * Like `Array.prototype.filter`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, filterAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     filterAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings.some(meaning => meaning.partOfSpeech === `adjective`)
 *     }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'lazy' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const filterAsync: {
  <From, To extends From>(fn: (value: From) => value is To): (asyncIterable: AsyncIterable<From>) => AsyncIterable<To>;
  <From, To extends From>(fn: (value: From) => value is To, asyncIterable: AsyncIterable<From>): AsyncIterable<To>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
};

/**
 * Returns a concur iterable that contains the values of `concurIterable`
 * excluding the values for which `fn` returns a value awaitable to a falsy
 * value.
 *
 * Like `Array.prototype.filter`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { asConcur, filterConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     filterConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings.some(meaning => meaning.partOfSpeech === `adjective`)
 *     }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'lazy' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const filterConcur: {
  <From, To extends From>(fn: (value: From) => value is To): (concurIterable: ConcurIterable<From>) => ConcurIterable<To>;
  <From, To extends From>(fn: (value: From) => value is To, concurIterable: ConcurIterable<From>): ConcurIterable<To>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
};

/**
 * Returns an iterable containing the values of `iterable` transformed by `fn`
 * in iteration order excluding the values for which `fn` returns `null` or
 * `undefined`.
 *
 * @example
 * ```js playground
 * import { filterMap, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [
 *       { sloth: `sloth` },
 *       { sloth: `lazy` },
 *       { notSloth: `active` },
 *       { sloth: `sleep` },
 *       { notSloth: `awake` },
 *     ],
 *     filterMap(object => object.sloth),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const filterMap: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => To | null | undefined): (iterable: Iterable<From>) => Iterable<NonNullable<To>>;
  <From, To extends unknown[] | []>(fn: (value: From) => To | null | undefined, iterable: Iterable<From>): Iterable<NonNullable<To>>;
  <From, To>(fn: (value: From) => To | null | undefined): (iterable: Iterable<From>) => Iterable<NonNullable<To>>;
  <From, To>(fn: (value: From) => To | null | undefined, iterable: Iterable<From>): Iterable<NonNullable<To>>;
};

/**
 * Returns an async iterable containing the values of `asyncIterable`
 * transformed by `fn` in iteration order excluding the values for which `fn`
 * returns a value awaitable to null or undefined.
 *
 * @example
 * ```js playground
 * import { asAsync, filterMapAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([
 *       { sloth: `sloth` },
 *       { sloth: `lazy` },
 *       { notSloth: `active` },
 *       { sloth: `sleep` },
 *       { notSloth: `awake` },
 *     ]),
 *     filterMapAsync(async object => {
 *       if (!object.sloth) {
 *         return null
 *       }
 *
 *       const response = await fetch(`${API_URL}/${object.sloth}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const filterMapAsync: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To | null | undefined>): (asyncIterable: AsyncIterable<From>) => AsyncIterable<NonNullable<To>>;
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To | null | undefined>, asyncIterable: AsyncIterable<From>): AsyncIterable<NonNullable<To>>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To | null | undefined>): (asyncIterable: AsyncIterable<From>) => AsyncIterable<NonNullable<To>>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To | null | undefined>, asyncIterable: AsyncIterable<From>): AsyncIterable<NonNullable<To>>;
};

/**
 * Returns a concur iterable containing the values of `concurIterable`
 * transformed by `fn` excluding the values for which `fn` returns a value
 * awaitable to `null` or `undefined`.
 *
 * @example
 * ```js playground
 * import { asConcur, filterMapConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([
 *       { sloth: `sloth` },
 *       { sloth: `lazy` },
 *       { notSloth: `active` },
 *       { sloth: `sleep` },
 *       { notSloth: `awake` },
 *     ]),
 *     filterMapConcur(async object => {
 *       if (!object.sloth) {
 *         return null
 *       }
 *
 *       const response = await fetch(`${API_URL}/${object.sloth}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const filterMapConcur: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To | null | undefined>): (concurIterable: ConcurIterable<From>) => ConcurIterable<NonNullable<To>>;
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To | null | undefined>, concurIterable: ConcurIterable<From>): ConcurIterable<NonNullable<To>>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To | null | undefined>): (concurIterable: ConcurIterable<From>) => ConcurIterable<NonNullable<To>>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To | null | undefined>, concurIterable: ConcurIterable<From>): ConcurIterable<NonNullable<To>>;
};

/**
 * Returns an iterable containing the values of `iterable` in iteration order
 * excluding the values of `excluded`.
 *
 * @example
 * ```js playground
 * import { exclude, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `active`, `sleep`, `awake`],
 *     exclude([`awake`, `active`]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Filters
 * @since v2.0.0
 */
declare const exclude: {
  (excluded: Iterable<unknown>): <Value>(iterable: Iterable<Value>) => Iterable<Value>;
  <Value>(excluded: Iterable<unknown>, iterable: Iterable<Value>): Iterable<Value>;
};

/**
 * Returns an async iterable containing the values of `asyncIterable` in
 * iteration order excluding the values of `excluded`.
 *
 * @example
 * ```js playground
 * import { asAsync, excludeAsync, flatMapAsync, map, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     flatMapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     excludeAsync([`adjective`, `verb`]),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'noun', 'noun' ]
 * ```
 *
 * @category Filters
 * @since v2.0.0
 */
declare const excludeAsync: {
  (excluded: Iterable<unknown>): <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
  <Value>(excluded: Iterable<unknown>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
};

/**
 * Returns a concur iterable containing the values of `concurIterable` in
 * iteration order excluding the values of `excluded`.
 *
 *
 * @example
 * ```js playground
 * import { asConcur, excludeConcur, flatMapConcur, map, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     flatMapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     excludeConcur([`adjective`, `verb`]),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'noun', 'noun' ]
 * ```
 *
 * @category Filters
 * @since v2.0.0
 */
declare const excludeConcur: {
  (excluded: Iterable<unknown>): <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
  <Value>(excluded: Iterable<unknown>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
};

/**
 * Returns an iterable containing the values of `iterable` in iteration order,
 * except values for which `fn` returns the same value are deduplicated.
 *
 * When values are deduplicated, the value earlier in iteration order wins.
 *
 * @example
 * ```js playground
 * import { pipe, reduce, toArray, uniqueBy } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     uniqueBy(word => word.length),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const uniqueBy: {
  <Value>(fn: (value: Value) => unknown): (iterable: Iterable<Value>) => Iterable<Value>;
  <Value>(fn: (value: Value) => unknown, iterable: Iterable<Value>): Iterable<Value>;
};

/**
 * Returns an async iterable containing the values of `asyncIterable` in
 * iteration order, except values for which `fn` returns a value awaitable to
 * the same value are deduplicated.
 *
 * When values are deduplicated, the value earlier in iteration order wins.
 *
 * @example
 * ```js playground
 * import { asAsync, pipe, reduceAsync, toArray, uniqueByAsync } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     uniqueByAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings[0].partOfSpeech
 *     }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'sleep' ]
 * ```
 *
 * @category Filters
 * @since v0.0.2
 */
declare const uniqueByAsync: {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
};

/**
 * Returns a concur iterable containing the values of `concurIterable`, except
 * values for which `fn` returns a value awaitable to the same value are
 * deduplicated.
 *
 * When values are deduplicated, the value earlier in iteration order wins.
 *
 * @example
 * ```js playground
 * import { asConcur, pipe, reduceConcur, toArray, uniqueByConcur } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     uniqueByConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings[0].partOfSpeech
 *     }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: These words may change between runs
 * //=> [ 'sloth', 'sleep' ]
 * ```
 *
 * @category Filters
 * @since v0.0.2
 */
declare const uniqueByConcur: {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
};

/**
 * Returns an iterable containing the values of `iterable` in iteration order,
 * except values are deduplicated if they are equal using `Object.is`.
 *
 * @example
 * ```js playground
 * import { pipe, reduce, toArray, unique } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `lazy`, `sleep`, `sloth`],
 *     unique,
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const unique: <Value>(iterable: Iterable<Value>) => Iterable<Value>;

/**
 * Returns an async iterable containing the values of `asyncIterable` in
 * iteration order, except values are deduplicated if they are equal using
 * `Object.is`.
 *
 * @example
 * ```js playground
 * import { asAsync, flatMapAsync, map, pipe, reduceAsync, toArray, uniqueAsync } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     flatMapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     uniqueAsync,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'noun', 'verb', 'adjective' ]
 * ```
 *
 * @category Filters
 * @since v0.0.2
 */
declare const uniqueAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;

/**
 * Returns a concur iterable containing the values of `concurIterable` in
 * iteration order, except values are deduplicated if they are equal using
 * `Object.is`.
 *
 * @example
 * ```js playground
 * import { asConcur, flatMapConcur, map, pipe, reduceConcur, toArray, uniqueConcur } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     flatMapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     uniqueConcur,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> [ 'noun', 'verb', 'adjective' ]
 * ```
 *
 * @category Filters
 * @since v0.0.2
 */
declare const uniqueConcur: <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;

/** @internal */
type Find = {
  <Value>(fn: (value: Value) => unknown): (iterable: Iterable<Value>) => Optional<Value>;
  <Value>(fn: (value: Value) => unknown, iterable: Iterable<Value>): Optional<Value>;
};

/** @internal */
type FindAsync = {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>;
};

/** @internal */
type FindConcur = {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, concurIterable: ConcurIterable<Value>): ConcurOptional<Value>;
};

/**
 * Returns an iterable containing the first value of `iterable` for which `fn`
 * returns a truthy value. Otherwise, returns an empty iterable.
 *
 * Like `Array.prototype.find`, but for iterables.
 *
 * @example
 * ```js playground
 * import { find, or, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     find(word => word.includes(`s`)),
 *     or(() => `not found!`),
 *   ),
 * )
 * //=> sloth
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     find(word => word.includes(`x`)),
 *     or(() => `not found!`),
 *   ),
 * )
 * //=> not found!
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const find: Find;

/**
 * Returns an async iterable containing the first value of `asyncIterable` for
 * which `fn` returns a value awaitable to a truthy value. Otherwise, returns an
 * empty async iterable.
 *
 * Like `Array.prototype.find`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, findAsync, orAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     findAsync(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
 *     orAsync(() => `not found!`),
 *   ),
 * )
 * //=> sloth
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     findAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *     orAsync(() => `not found!`),
 *   ),
 * )
 * //=> not found!
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const findAsync: FindAsync;

/**
 * Returns a concur iterable containing the first value of `concurIterable` for
 * which `fn` returns a value awaitable to a truthy value. Otherwise, returns an
 * empty concur iterable.
 *
 * If a non-empty concur iterable is returned, then the returned concur iterable
 * does not reject, even if the input `concurIterable` does and even if the
 * found value was emitted after an erroring value.
 *
 * If an empty concur iterable is returned, then it will reject if the input
 * `concurIterable` does.
 *
 * Like `Array.prototype.find`, but for concur iterables. The error semantics
 * are similar to `Promise.any`.
 *
 * @example
 * ```js playground
 * import { asConcur, findConcur, orConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     findConcur(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
 *     orConcur(() => `not found!`),
 *   ),
 * )
 * // NOTE: This word may change between runs
 * //=> sloth
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     findConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *     orConcur(() => `not found!`),
 *   ),
 * )
 * //=> not found!
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const findConcur: FindConcur;

/**
 * Returns an iterable containing the last value of `iterable` for which `fn`
 * returns a truthy value. Otherwise, returns an empty iterable.
 *
 * @example
 * ```js playground
 * import { findLast, or, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     findLast(word => word.includes(`s`)),
 *     or(() => `not found!`),
 *   ),
 * )
 * //=> sleep
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     findLast(word => word.includes(`x`)),
 *     or(() => `not found!`),
 *   ),
 * )
 * //=> not found!
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const findLast: Find;

/**
 * Returns an async iterable containing the last value of `asyncIterable` for
 * which `fn` returns a value awaitable to a truthy value. Otherwise, returns an
 * empty async iterable.
 *
 * @example
 * ```js playground
 * import { asAsync, findLastAsync, orAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     findLastAsync(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
 *     orAsync(() => `not found!`),
 *   ),
 * )
 * //=> sleep
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     findLastAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *     orAsync(() => `not found!`),
 *   ),
 * )
 * //=> not found!
 * ```
 *
 * @category Filters
 * @since v0.0.1
 */
declare const findLastAsync: FindAsync;

/**
 * Returns a concur iterable containing the last value of `concurIterable` for
 * which `fn` returns a value awaitable to a truthy value. Otherwise, returns an
 * empty concur iterable.
 *
 * If a non-empty concur iterable is returned, then the returned concur iterable
 * does not reject, even if the input `concurIterable` does and even if the
 * found value was emitted after an erroring value.
 *
 * If an empty concur iterable is returned, then it will reject if the input
 * `concurIterable` does.
 *
 * Like `Array.prototype.findLast`, but for concur iterables. The error
 * semantics are similar to `Promise.any`.
 *
 * WARNING: This function always waits for `concurIterable` to finish iterating
 * because that's the only way to ensure the found value is the last one.
 *
 * @example
 * ```js playground
 * import { asConcur, findLastConcur, orConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     findLastConcur(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
 *     orConcur(() => `not found!`),
 *   ),
 * )
 * // NOTE: This word may change between runs
 * //=> sleep
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     findLastConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *     orConcur(() => `not found!`),
 *   ),
 * )
 * //=> not found!
 * ```
 *
 * @category Filters
 * @since v0.0.2
 */
declare const findLastConcur: FindConcur;
//#endregion
//#region src/operations/generators.d.ts
/**
 * Returns an iterable containing the keys of `object`.
 *
 * This differs from `Map.prototype.keys` in that the returned iterable can be
 * iterated multiple times and differs from `Object.keys` in that the returned
 * iterable is opaque.
 *
 * @example
 * ```js playground
 * import { keys, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     keys([`sloth`, `lazy`, `sleep`]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 0, 1, 2 ]
 *
 * console.log(
 *   pipe(
 *     keys({
 *       sloth: 1,
 *       lazy: 2,
 *       sleep: 3,
 *     }),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 *
 * console.log(
 *   pipe(
 *     keys(
 *       new Map([
 *         [`sloth`, 1],
 *         [`lazy`, 2],
 *         [`sleep`, 3],
 *       ]),
 *     ),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Generators
 * @since v0.1.0
 */
declare const keys: {
  <Key>(object: ReadonlyMap<Key, unknown>): Iterable<Key>;
  <Key extends PropertyKey>(object: Readonly<Record<Key, unknown>>): Iterable<Key>;
};

/**
 * Returns an iterable containing the values of `object`.
 *
 * This differs from `Map.prototype.values` and `Set.prototype.values` in that
 * the returned iterable can be iterated multiple times and differs from
 * `Object.values` in that the returned iterable is opaque.
 *
 * @example
 * ```js playground
 * import { pipe, reduce, toArray, values } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     values([`sloth`, `lazy`, `sleep`]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy, 'sleep' ]
 *
 * console.log(
 *   pipe(
 *     values({
 *       sloth: 1,
 *       lazy: 2,
 *       sleep: 3,
 *     }),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3 ]
 *
 * console.log(
 *   pipe(
 *     values(new Set([`sloth`, `lazy`, `sleep`])),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy, 'sleep' ]
 *
 * console.log(
 *   pipe(
 *     values(
 *       new Map([
 *         [`sloth`, 1],
 *         [`lazy`, 2],
 *         [`sleep`, 3],
 *       ]),
 *     ),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3 ]
 * ```
 *
 * @category Generators
 * @since v0.1.0
 */
declare const values: <Value>(object: ReadonlyMap<unknown, Value> | ReadonlySet<Value> | Readonly<Record<PropertyKey, Value>>) => Iterable<Value>;

/**
 * Returns an iterable containing the entries of `object`.
 *
 * This differs from `Map.prototype.entries` in that the returned iterable can
 * be iterated multiple times and differs from `Object.entries` in that the
 * returned iterable is opaque.
 *
 * @example
 * ```js playground
 * import { entries, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     entries([`sloth`, `lazy`, `sleep`]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [
 * //=>   [ 0, 'sloth' ],
 * //=>   [ 1, 'lazy' ],
 * //=>   [ 2, 'sleep' ]
 * //=> ]
 *
 * console.log(
 *   pipe(
 *     entries({
 *       sloth: 1,
 *       lazy: 2,
 *       sleep: 3,
 *     }),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [
 * //=>   [ 'sloth', 1 ],
 * //=>   [ 'lazy', 2 ],
 * //=>   [ 'sleep', 3 ]
 * //=> ]
 *
 * console.log(
 *   pipe(
 *     entries(
 *       new Map([
 *         [`sloth`, 1],
 *         [`lazy`, 2],
 *         [`sleep`, 3],
 *       ]),
 *     ),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [
 * //=>   [ 'sloth', 1 ],
 * //=>   [ 'lazy', 2 ],
 * //=>   [ 'sleep', 3 ]
 * //=> ]
 * ```
 *
 * @category Generators
 * @since v0.1.0
 */
declare const entries: {
  <Key, Value>(object: {
    entries: () => Iterable<[Key, Value]>;
  }): Iterable<[Key, Value]>;
  <Key extends PropertyKey, Value>(object: Readonly<Record<Key, Value>>): Iterable<[Key, Value]>;
};

/**
 * Returns an infinite iterable that yields `seed` for its first value and then
 * yields the result of applying `fn` to its previously yielded value for every
 * subsequent value.
 *
 * @example
 * ```js playground
 * import { generate, pipe, reduce, take, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     `sloth`,
 *     generate(previousValue => `${previousValue} ${previousValue}`),
 *     take(4),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [
 * //=>   'sloth',
 * //=>   'sloth sloth',
 * //=>   'sloth sloth sloth sloth',
 * //=>   'sloth sloth sloth sloth sloth sloth sloth sloth'
 * //=> ]
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const generate: {
  <Value>(fn: (previousValue: Value) => Value): (seed: Value) => Iterable<Value>;
  <Value>(fn: (previousValue: Value) => Value, seed: Value): Iterable<Value>;
};

/**
 * Returns an infinite async iterable that yields `seed` for its first value and
 * then yields the awaited result of applying `fn` to its previously yielded
 * value for every subsequent value.
 *
 * @example
 * ```js playground
 * import { generateAsync, pipe, reduceAsync, takeAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     `sleep`,
 *     generateAsync(async previousWord => {
 *       const response = await fetch(`${API_URL}/${previousWord}`)
 *       const [{ meanings }] = await response.json()
 *       return meanings[0].partOfSpeech
 *     }),
 *     takeAsync(4),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sleep', 'verb', 'noun', 'noun' ]
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const generateAsync: {
  <Value>(fn: (previousValue: Value) => MaybePromiseLike<Value>): (seed: Value) => AsyncIterable<Value>;
  <Value>(fn: (previousValue: Value) => MaybePromiseLike<Value>, seed: Value): AsyncIterable<Value>;
};

/**
 * Returns an infinite iterable that repeatedly yields `value`.
 *
 * @example
 * ```js playground
 * import { join, pipe, repeat, take } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     repeat(`sloth`),
 *     take(4),
 *     join(`, `),
 *   ),
 * )
 * //=> sloth, sloth, sloth, sloth
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const repeat: <Value>(value: Value) => Iterable<Value>;

/**
 * Returns an infinite iterable that repeatedly yields the values of `iterable`
 * in iteration order.
 *
 * WARNING: This function does not buffer the values of `iterable` for future
 * cycles. It reiterates `iterable` each cycle.
 *
 * @example
 * ```js playground
 * import { cycle, join, pipe, take } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `lazy`]),
 *     take(6),
 *     join(`, `),
 *   ),
 * )
 * //=> sloth, lazy, sloth, lazy, sloth, lazy
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const cycle: <Value>(iterable: Iterable<Value>) => Iterable<Value>;

/**
 * Returns an infinite async iterable that repeatedly yields the values of
 * `asyncIterable`.
 *
 * WARNING: This function does not buffer the values of `asyncIterable` for
 * future cycles. It reiterates `asyncIterable` each cycle.
 *
 * @example
 * ```js playground
 * import { asAsync, cycleAsync, joinAsync, mapAsync, pipe, takeAsync } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     cycleAsync,
 *     takeAsync(6),
 *     joinAsync(`, `),
 *   ),
 * )
 * //=> /slɑθ/, /ˈleɪzi/, /sliːp/, /slɑθ/, /ˈleɪzi/, /sliːp/
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const cycleAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;

/**
 * An iterable that yields integers in a range.
 *
 * See {@link RangeIterable.step} for obtaining a new iterable that skips
 * integers in steps.
 *
 * @category Generators
 * @since v2.0.0
 */
type RangeIterable = Iterable<number> & {
  /**
   * Returns an iterable that yields integers in the same range as the original
   * {@link RangeIterable}, but steps through the range in increments of `step`
   * instead of 1.
   *
   * @throws if `step` is not a positive integer.
   *
   * @example
   * ```js playground
   * import { join, pipe, rangeTo } from 'lfi'
   *
   * console.log(
   *   pipe(
   *     rangeTo(0, 6).step(2),
   *     join(`, `),
   *   ),
   * )
   * //=> 0, 2, 4, 6
   * ```
   */
  step: <Step extends number>(step: PositiveInteger<Step>) => Iterable<number>;
};

/** @internal */
type Range = {
  <Start extends number>(start: Integer<Start>): <End extends number>(end: Integer<End>) => RangeIterable;
  <Start extends number, End extends number>(start: Integer<Start>, end: Integer<End>): RangeIterable;
};

/**
 * Returns a {@link RangeIterable} that yields the integers between `start` and
 * `end`, including `start` and `end`.
 *
 * @throws if either `start` or `end` is not an integer.
 *
 * @example
 * ```js playground
 * import { join, pipe, rangeTo } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     rangeTo(0, 6),
 *     join(`, `),
 *   ),
 * )
 * //=> 0, 1, 2, 3, 4, 5, 6
 *
 * console.log(
 *   pipe(
 *     rangeTo(0, 6).step(2),
 *     join(`, `),
 *   ),
 * )
 * //=> 0, 2, 4, 6
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const rangeTo: Range;

/**
 * Returns a {@link RangeIterable} that yields the integers between `start` and
 * `end` including `start`, but excluding `end`.
 *
 * @throws if either `start` or `end` is not an integer.
 *
 * @example
 * ```js playground
 * import { join, pipe, rangeUntil } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     rangeUntil(0, 6),
 *     join(`, `),
 *   ),
 * )
 * //=> 0, 1, 2, 3, 4, 5
 *
 * console.log(
 *   pipe(
 *     rangeUntil(0, 6).step(2),
 *     join(`, `),
 *   ),
 * )
 * //=> 0, 2, 4
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const rangeUntil: Range;
//#endregion
//#region src/operations/predicates.d.ts
/** @internal */
type Predicate = {
  <Value>(fn: (value: Value) => unknown): (iterable: Iterable<Value>) => boolean;
  <Value>(fn: (value: Value) => unknown, iterable: Iterable<Value>): boolean;
};

/** @internal */
type PredicateAsync = {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (asyncIterable: AsyncIterable<Value>) => Promise<boolean>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, asyncIterable: AsyncIterable<Value>): Promise<boolean>;
};

/** @internal */
type PredicateConcur = {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (concurIterable: ConcurIterable<Value>) => Promise<boolean>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, concurIterable: ConcurIterable<Value>): Promise<boolean>;
};

/**
 * Returns `true` if `fn` returns a truthy value for all values of `iterable`.
 * Otherwise returns `false`.
 *
 * Like `Array.prototype.every`, but for iterables.
 *
 * @example
 * ```js playground
 * import { all, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     all(word => word.includes(`l`)),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     all(word => word.includes(`s`)),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.1
 */
declare const all: Predicate;

/**
 * Returns a promise that resolves to `true` if `fn` returns a truthy value or a
 * promise that resolves to a truthy value for all values of `asyncIterable`.
 * Otherwise returns a promise that resolves to `false`.
 *
 * Like `Array.prototype.every`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { allAsync, asAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     allAsync(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     allAsync(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.1
 */
declare const allAsync: PredicateAsync;

/**
 * Returns a promise that resolves to `true` if `fn` returns a truthy value or a
 * promise that resolves to a truthy value for all values of `concurIterable`.
 * Otherwise returns a promise that resolves to `false`.
 *
 * Like `Array.prototype.every`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { allConcur, asConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     allConcur(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     allConcur(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.2
 */
declare const allConcur: PredicateConcur;

/**
 * Returns `true` if `fn` returns a truthy value for any value of `iterable`.
 * Otherwise returns `false`.
 *
 * Like `Array.prototype.some`, but for iterables.
 *
 * @example
 * ```js playground
 * import { any, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     any(word => word.includes(`s`)),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     any(word => word.includes(`x`)),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.1
 */
declare const any: Predicate;

/**
 * Returns a promise that resolves to `true` if `fn` returns a truthy value or a
 * promise that resolves to a truthy value for any value of `asyncIterable`.
 * Otherwise returns a promise that resolves to `false`.
 *
 * Like `Array.prototype.some`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { anyAsync, asAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     anyAsync(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     anyAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.1
 */
declare const anyAsync: PredicateAsync;

/**
 * Returns a promise that resolves to `true` if `fn` returns a truthy value or a
 * promise that resolves to a truthy value for any value of `concurIterable`.
 * Otherwise returns a promise that resolves to `false`.
 *
 * Like `Array.prototype.some`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { anyConcur, asConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     anyConcur(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     anyConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.2
 */
declare const anyConcur: PredicateConcur;

/**
 * Returns `true` if `fn` returns a falsy value for all values of `iterable`.
 * Otherwise returns `false`.
 *
 * @example
 * ```js playground
 * import { none, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     none(word => word.includes(`s`)),
 *   ),
 * )
 * //=> false
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     none(word => word.includes(`x`)),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @category Predicates
 * @since v0.0.1
 */
declare const none: Predicate;

/**
 * Returns a promise that resolves to `true` if `fn` returns a falsy value or a
 * promise that resolves to a falsy value for all values of `asyncIterable`.
 * Otherwise returns a promise that resolves to `false`.
 *
 * @example
 * ```js playground
 * import { noneAsync, asAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     noneAsync(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
 *   ),
 * )
 * //=> false
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     noneAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @category Predicates
 * @since v0.0.1
 */
declare const noneAsync: PredicateAsync;

/**
 * Returns a promise that resolves to `true` if `fn` returns a falsy value or a
 * promise that resolves to a falsy value for all values of `concurIterable`.
 * Otherwise returns a promise that resolves to `false`.
 *
 * @example
 * ```js playground
 * import { noneConcur, asConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     noneConcur(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     noneConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.2
 */
declare const noneConcur: PredicateConcur;

/**
 * Returns `true` if any value of `iterable` is equal to `searchElement` using
 * `Object.is`. Otherwise returns `false`.
 *
 * Like `Array.prototype.includes`, but for iterables.
 *
 * @example
 * ```js playground
 * import { includes, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     includes(`lazy`),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     includes(`awake`),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.2
 */
declare const includes: {
  (searchElement: unknown): <Value>(iterable: Iterable<Value>) => boolean;
  <Value>(searchElement: unknown, iterable: Iterable<Value>): boolean;
};

/**
 * Returns a promise that resolves to `true` if any value of `asyncIterable` is
 * equal to `searchElement` using `Object.is`. Otherwise returns a promise that
 * resolves to `false`.
 *
 * Like `Array.prototype.includes`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, flatMapAsync, includesAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     flatMapAsync(getPartsOfSpeech),
 *     includesAsync(`noun`),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     flatMapAsync(getPartsOfSpeech),
 *     includesAsync(`adverb`),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.2
 */
declare const includesAsync: {
  (searchElement: unknown): <Value>(asyncIterable: AsyncIterable<Value>) => Promise<boolean>;
  <Value>(searchElement: unknown, asyncIterable: AsyncIterable<Value>): Promise<boolean>;
};

/**
 * Returns a promise that resolves to `true` if any value of `concurIterable` is
 * equal to `searchElement` using `Object.is`. Otherwise returns a promise that
 * resolves to `false`.
 *
 * Like `Array.prototype.includes`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { asConcur, flatMapConcur, includesConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 * const getPartsOfSpeech = async word => {
 *   const response = await fetch(`${API_URL}/${word}`)
 *   const [{ meanings }] = await response.json()
 *   return meanings.map(meaning => meaning.partOfSpeech)
 * }
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     flatMapConcur(getPartsOfSpeech),
 *     includesConcur(`noun`),
 *   ),
 * )
 * //=> true
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     flatMapConcur(getPartsOfSpeech),
 *     includesConcur(`adverb`),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @category Predicates
 * @since v0.0.2
 */
declare const includesConcur: {
  (searchElement: unknown): <Value>(concurIterable: ConcurIterable<Value>) => Promise<boolean>;
  <Value>(searchElement: unknown, concurIterable: ConcurIterable<Value>): Promise<boolean>;
};
//#endregion
//#region src/operations/side-effects.d.ts
/**
 * Returns an iterable equivalent to `iterable` that applies `fn` to each value
 * of `iterable` as it is iterated.
 *
 * @example
 * ```js playground
 * import { each, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     each(console.log),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> sloth
 * //=> lazy
 * //=> sleep
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Side effects
 * @since v0.0.1
 */
declare const each: {
  <From, To extends From>(fn: (value: From) => asserts value is To): (iterable: Iterable<From>) => Iterable<To>;
  <From, To extends From>(fn: (value: From) => asserts value is To, iterable: Iterable<From>): Iterable<To>;
  <Value>(fn: (value: Value) => unknown): (iterable: Iterable<Value>) => Iterable<Value>;
  <Value>(fn: (value: Value) => unknown, iterable: Iterable<Value>): Iterable<Value>;
};

/**
 * Returns an async iterable equivalent to `asyncIterable` that applies `fn` to
 * each value of `asyncIterable` as it is iterated.
 *
 * The result of applying `fn` to a value is awaited before yielding and then
 * moving on to the next value.
 *
 * @example
 * ```js playground
 * import { asAsync, eachAsync, mapAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     eachAsync(console.log),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Side effects
 * @since v0.0.1
 */
declare const eachAsync: {
  <Value>(fn: (value: Value) => PromiseLike<unknown>): (asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
  <Value>(fn: (value: Value) => PromiseLike<unknown>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
  <From, To extends From>(fn: (value: From) => asserts value is To): (asyncIterable: AsyncIterable<From>) => AsyncIterable<To>;
  <From, To extends From>(fn: (value: From) => asserts value is To, asyncIterable: AsyncIterable<From>): AsyncIterable<To>;
};

/**
 * Returns an concur iterable equivalent to `concurIterable` that applies `fn`
 * to each value of `concurIterable` as it is iterated.
 *
 * The result of applying `fn` to a value is awaited before yielding.
 *
 * @example
 * ```js playground
 * import { asConcur, eachConcur, mapConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     eachConcur(console.log),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Side effects
 * @since v0.0.1
 */
declare const eachConcur: {
  <Value>(fn: (value: Value) => PromiseLike<unknown>): (concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
  <Value>(fn: (value: Value) => PromiseLike<unknown>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
  <From, To extends From>(fn: (value: From) => asserts value is To): (concurIterable: ConcurIterable<From>) => ConcurIterable<To>;
  <From, To extends From>(fn: (value: From) => asserts value is To, concurIterable: ConcurIterable<From>): ConcurIterable<To>;
};

/**
 * Applies `fn` to each value of `iterable`.
 *
 * Like `Array.prototype.forEach`, but for iterables.
 *
 * @example
 * ```js playground
 * import { forEach, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     forEach(console.log),
 *   ),
 * )
 * //=> sloth
 * //=> lazy
 * //=> sleep
 * ```
 *
 * @category Side effects
 * @since v0.0.1
 */
declare const forEach: {
  <Value>(fn: (value: Value) => unknown): (iterable: Iterable<Value>) => void;
  <Value>(fn: (value: Value) => unknown, iterable: Iterable<Value>): void;
};

/**
 * Returns a promise that resolves when `fn` has been applied to each value of
 * `asyncIterable` and the result of each application has been awaited.
 *
 * The result of applying `fn` to a value is awaited before moving on to the
 * next value.
 *
 * Like `Array.prototype.forEach`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, forEachAsync, mapAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     forEachAsync(console.log),
 *   ),
 * )
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * ```
 *
 * @category Side effects
 * @since v0.0.1
 */
declare const forEachAsync: {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (asyncIterable: AsyncIterable<Value>) => Promise<void>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, asyncIterable: AsyncIterable<Value>): Promise<void>;
};

/**
 * Returns a promise that resolves when `fn` has been applied to each value of
 * `concurIterable` and the result of each application has been awaited.
 *
 * The promise rejects if `concurIterable` rejects. However, `fn` will be called
 * with every non-erroring value before the promise rejects, even if
 * non-erroring values arrives after erroring ones.
 *
 * Like `Array.prototype.forEach`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { asConcur, forEachConcur, mapConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     forEachConcur(console.log),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * ```
 *
 * @category Side effects
 * @since v0.0.1
 */
declare const forEachConcur: {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (concurIterable: ConcurIterable<Value>) => Promise<void>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, concurIterable: ConcurIterable<Value>): Promise<void>;
};

/**
 * Iterates through `iterable` causing lazy operations to run.
 *
 * @example
 * ```js playground
 * import { consume, each, pipe } from 'lfi'
 *
 * const iterable = pipe(
 *   [`sloth`, `lazy`, `sleep`],
 *   each(console.log),
 * )
 * // No output
 *
 * consume(iterable)
 * //=> sloth
 * //=> lazy
 * //=> sleep
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const consume: (iterable: Iterable<unknown>) => void;

/**
 * Iterates through `asyncIterable` causing lazy operations to run.
 *
 * @example
 * ```js playground
 * import { asAsync, consumeAsync, eachAsync, mapAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const asyncIterable = pipe(
 *   asAsync([`sloth`, `lazy`, `sleep`]),
 *   mapAsync(async word => {
 *     const response = await fetch(`${API_URL}/${word}`)
 *     return (await response.json())[0].phonetic
 *   }),
 *   eachAsync(console.log),
 * )
 * // No output
 *
 * await consumeAsync(asyncIterable)
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const consumeAsync: (asyncIterable: AsyncIterable<unknown>) => Promise<void>;

/**
 * Returns a promise that resolves after iterating through the `concurIterable`
 * and causing lazy operations to run.
 *
 * The promise rejects if `concurIterable` rejects.
 *
 * @example
 * ```js playground
 * import { asConcur, consumeConcur, eachConcur, mapConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const asyncIterable = pipe(
 *   asConcur([`sloth`, `lazy`, `sleep`]),
 *   mapConcur(async word => {
 *     const response = await fetch(`${API_URL}/${word}`)
 *     return (await response.json())[0].phonetic
 *   }),
 *   eachConcur(console.log),
 * )
 * // No output
 *
 * await consumeConcur(asyncIterable)
 * // NOTE: This order may change between runs
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const consumeConcur: (concurIterable: ConcurIterable<unknown>) => Promise<void>;

/**
 * Returns an iterable equivalent to `iterable` that iterates over `iterable` at
 * most once by lazily caching the values from the first iteration.
 *
 * @example
 * ```js playground
 * import { each, cache, pipe } from 'lfi'
 *
 * const iterable = pipe(
 *   [`sloth`, `lazy`, `sleep`],
 *   each(console.log),
 *   cache,
 * )
 * // No output
 *
 * console.log([...iterable])
 * //=> sloth
 * //=> lazy
 * //=> sleep
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 *
 * console.log([...iterable])
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const cache: <Value>(iterable: Iterable<Value>) => Iterable<Value>;

/**
 * Returns an async iterable equivalent to `asyncIterable` that iterates over
 * `asyncIterable` at most once by lazily caching the values from the first
 * iteration.
 *
 * @example
 * ```js playground
 * import { asAsync, eachAsync, cacheAsync, mapAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const asyncIterable = pipe(
 *   asAsync([`sloth`, `lazy`, `sleep`]),
 *   mapAsync(async word => {
 *     const response = await fetch(`${API_URL}/${word}`)
 *     return (await response.json())[0].phonetic
 *   }),
 *   eachAsync(console.log),
 *   cacheAsync,
 * )
 * // No output
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const cacheAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;

/**
 * Returns a concur iterable equivalent to `concurIterable` that iterates over
 * `concurIterable` at most once by lazily caching the values from the first
 * iteration.
 *
 * @example
 * ```js playground
 * import { asConcur, eachConcur, cacheConcur, mapConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * const asyncIterable = pipe(
 *   asConcur([`sloth`, `lazy`, `sleep`]),
 *   mapConcur(async word => {
 *     const response = await fetch(`${API_URL}/${word}`)
 *     return (await response.json())[0].phonetic
 *   }),
 *   eachConcur(console.log),
 *   cacheConcur,
 * )
 * // No output
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> /slɑθ/
 * //=> /ˈleɪzi/
 * //=> /sliːp/
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const cacheConcur: <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
//#endregion
//#region src/operations/splices.d.ts
/**
 * Returns an iterable containing the values of `iterable` in iteration order
 * starting with the first value for which `fn` returns a falsy value.
 *
 * @example
 * ```js playground
 * import { dropWhile, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `active`, `sleep`, `awake`],
 *     dropWhile(word => word.includes(`l`)),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'active', 'sleep', 'awake' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const dropWhile: SubWhile;

/**
 * Returns an async iterable containing the values of `asyncIterable` in
 * iteration order starting with the first value for which `fn` returns a value
 * awaitable to a falsy value.
 *
 * @example
 * ```js playground
 * import { asAsync, dropWhileAsync, flatMapAsync, map, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     flatMapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     dropWhileAsync(partOfSpeech => partOfSpeech.length === 4),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'adjective', 'verb' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const dropWhileAsync: SubWhileAsync;

/**
 * Returns a concur iterable containing the values of `concurIterable` in
 * iteration order starting with the first value for which `fn` returns a value
 * awaitable to a falsy value.
 *
 * @example
 * ```js playground
 * import { asConcur, dropWhileConcur, flatMapConcur, map, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     flatMapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     dropWhileConcur(partOfSpeech => partOfSpeech.length === 4),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This may change between runs
 * //=> [ 'adjective', 'verb' ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const dropWhileConcur: SubWhileConcur;

/**
 * Returns an iterable containing the values of `iterable` in iteration order
 * up until but not including the first value for which `fn` returns a falsy
 * value.
 *
 * @example
 * ```js playground
 * import { pipe, reduce, takeWhile, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `active`, `sleep`, `awake`],
 *     takeWhile(word => word.includes(`l`)),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const takeWhile: SubWhile;

/**
 * Returns an async iterable containing the values of `asyncIterable` in
 * iteration order up until but not including the first value for which `fn`
 * returns a value awaitable to a falsy value.
 *
 * @example
 * ```js playground
 * import { asAsync, flatMapAsync, map, pipe, reduceAsync, takeWhileAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     flatMapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     takeWhileAsync(partOfSpeech => partOfSpeech.length === 4),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'noun', 'verb', 'noun', 'verb' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const takeWhileAsync: SubWhileAsync;

/**
 * Returns a concur iterable containing the values of `concurIterable` in
 * iteration order up until but not including the first value for which `fn`
 * returns a value awaitable to a falsy value.
 *
 * @example
 * ```js playground
 * import { asConcur, flatMapConcur, map, pipe, reduceConcur, takeWhileConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     flatMapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     takeWhileConcur(partOfSpeech => partOfSpeech.length === 4),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This may change between runs
 * //=> [ 'noun', 'verb', 'noun', 'verb' ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const takeWhileConcur: SubWhileConcur;

/** @internal */
type SubWhile = {
  <Value>(fn: (value: Value) => unknown): (iterable: Iterable<Value>) => Iterable<Value>;
  <Value>(fn: (value: Value) => unknown, iterable: Iterable<Value>): Iterable<Value>;
};

/** @internal */
type SubWhileAsync = {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
};

/** @internal */
type SubWhileConcur = {
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>): (concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<unknown>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
};

/**
 * Returns an iterable containing the values of `iterable` in iteration order
 * except for the first `count` values.
 *
 * If the `count` is greater than the number of values in `iterable`, then an
 * empty iterable is returned.
 *
 * @throws if `count` isn't a non-negative integer.
 *
 * @example
 * ```js playground
 * import { drop, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`active`, `awake`, `sloth`, `lazy`, `sleep`],
 *     drop(2),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const drop: Sub;

/**
 * Returns an async iterable containing the values of `asyncIterable` in
 * iteration order except for the first `count` values.
 *
 * If the `count` is greater than the number of values in `asyncIterable`, then
 * an empty async iterable is returned.
 *
 * @throws if `count` isn't a non-negative integer.
 *
 * @example
 * ```js playground
 * import { asAsync, dropAsync, mapAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`active`, `awake`, `sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     dropAsync(2),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const dropAsync: SubAsync;

/**
 * Returns a concur iterable containing the values of `concurIterable` in
 * iteration order except for the first `count` values.
 *
 * If the `count` is greater than the number of values in `concurIterable`, then
 * an empty concur iterable is returned.
 *
 * @throws if `count` isn't a non-negative integer.
 *
 * @example
 * ```js playground
 * import { asConcur, dropConcur, mapConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`active`, `awake`, `sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     dropConcur(2),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This may change between runs
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const dropConcur: SubConcur;

/**
 * Returns an iterable containing the first `count` values of `iterable` in
 * iteration order.
 *
 * If the `count` is greater than the number of values in `iterable`, then an
 * iterable equivalent `iterable` is returned.
 *
 * @throws if `count` isn't a non-negative integer.
 *
 * @example
 * ```js playground
 * import { pipe, reduce, take, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`, `active`, `awake`],
 *     take(3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const take: Sub;

/**
 * Returns an async iterable containing the first `count` values of
 * `asyncIterable` in iteration order.
 *
 * If the `count` is greater than the number of values in `asyncIterable`, then
 * an async iterable equivalent `asyncIterable` is returned.
 *
 * @throws if `count` isn't a non-negative integer.
 *
 * ```js playground
 * import { asAsync, mapAsync, pipe, reduceAsync, takeAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`, `active`, `awake`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     takeAsync(3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const takeAsync: SubAsync;

/**
 * Returns a concur iterable containing the first `count` values of
 * `concurIterable` in iteration order.
 *
 * If the `count` is greater than the number of values in `concurIterable`, then
 * a concur iterable equivalent `concurIterable` is returned.
 *
 * @throws if `count` isn't a non-negative integer.
 *
 * ```js playground
 * import { asConcur, mapConcur, pipe, reduceConcur, takeConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`, `active`, `awake`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     takeConcur(3),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const takeConcur: SubConcur;

/** @internal */
type Sub = {
  <Count extends number>(count: NonNegativeInteger<Count>): <Value>(iterable: Iterable<Value>) => Iterable<Value>;
  <Count extends number, Value>(count: NonNegativeInteger<Count>, iterable: Iterable<Value>): Iterable<Value>;
};

/** @internal */
type SubAsync = {
  <Count extends number>(count: NonNegativeInteger<Count>): <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
  <Count extends number, Value>(count: NonNegativeInteger<Count>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
};

/** @internal */
type SubConcur = {
  <Count extends number>(count: NonNegativeInteger<Count>): <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
  <Count extends number, Value>(count: NonNegativeInteger<Count>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
};

/**
 * Returns an iterable containing the first value of `iterable`, or an empty
 * iterable if `iterable` is empty.
 *
 * @example
 * ```js playground
 * import { first, or, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     first,
 *     or(() => `empty`),
 *   ),
 * )
 * //=> sloth
 *
 * console.log(
 *   pipe(
 *     [],
 *     first,
 *     or(() => `empty`),
 *   ),
 * )
 * //=> empty
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const first: <Value>(iterable: Iterable<Value>) => Optional<Value>;

/**
 * Returns an async iterable containing the first value of `asyncIterable`, or
 * an empty async iterable if `asyncIterable` is empty.
 *
 * @example
 * ```js playground
 * import { asAsync, firstAsync, mapAsync, orAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     firstAsync,
 *     orAsync(() => `empty`),
 *   ),
 * )
 * //=> /slɑθ/
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const firstAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;

/**
 * Returns a concur iterable containing the first value of `concurIterable`, or
 * an empty concur iterable if `concurIterable` is empty.
 *
 * @example
 * ```js playground
 * import { asConcur, firstConcur, mapConcur, orConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     firstConcur,
 *     orConcur(() => `empty`),
 *   ),
 * )
 * // NOTE: This may change between runs
 * //=> /slɑθ/
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const firstConcur: <Value>(concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;

/**
 * Returns an iterable containing the last value of `iterable`, or an empty
 * iterable if `iterable` is empty.
 *
 * @example
 * ```js playground
 * import { last, or, pipe } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     last,
 *     or(() => `empty`),
 *   ),
 * )
 * //=> sleep
 *
 * console.log(
 *   pipe(
 *     [],
 *     last,
 *     or(() => `empty`),
 *   ),
 * )
 * //=> empty
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const last: <Value>(iterable: Iterable<Value>) => Optional<Value>;

/**
 * Returns an async iterable containing the last value of `asyncIterable`, or
 * an empty async iterable if `asyncIterable` is empty.
 *
 * @example
 * ```js playground
 * import { asAsync, lastAsync, mapAsync, orAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     lastAsync,
 *     orAsync(() => `empty`),
 *   ),
 * )
 * //=> /sliːp/
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const lastAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;

/**
 * Returns a concur iterable containing the last value of `concurIterable`, or
 * an empty concur iterable if `concurIterable` is empty.
 *
 * @example
 * ```js playground
 * import { asConcur, lastConcur, mapConcur, orConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     lastConcur,
 *     orConcur(() => `empty`),
 *   ),
 * )
 * // NOTE: This may change between runs
 * //=> /sliːp/
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const lastConcur: <Value>(concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;

/**
 * Returns an iterable containing the values of `iterable` between `start` and
 * `end` (exclusive) of `iterable`.
 *
 * If any part of the range between `start` and `end` is outside the bounds of
 * the iterable, then that part is excluded from the returned iterable. Thus,
 * the returned iterable may be empty.
 *
 * WARNING: This function linearly iterates up to `end` because iterables do
 * not support random access.
 *
 * @throws if either `start` or `end` is not a non-negative integer, or if
 * `start` is greater than `end`.
 *
 * @example
 * ```js
 * const iterable = [`sloth`, `more sloth`, `even more sloth`]
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     slice(0, 3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     slice(0, 42),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     slice(1, 3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     slice(3, 5),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> []
 * ```
 *
 * @category Splices
 * @since v3.5.0
 */
declare const slice: {
  <Start extends number>(start: NonNegativeInteger<Start>): {
    <End extends number>(End: NonNegativeInteger<End>): <Value>(iterable: Iterable<Value>) => Iterable<Value>;
    <End extends number, Value>(End: NonNegativeInteger<End>, iterable: Iterable<Value>): Iterable<Value>;
  };
  <Start extends number, End extends number>(start: NonNegativeInteger<Start>, End: NonNegativeInteger<End>): <Value>(iterable: Iterable<Value>) => Iterable<Value>;
  <Start extends number, End extends number, Value>(start: NonNegativeInteger<Start>, End: NonNegativeInteger<End>, iterable: Iterable<Value>): Iterable<Value>;
};

/**
 * Returns an async iterable containing the values of `asyncIterable` between
 * `start` and `end` (exclusive) of `asyncIterable`.
 *
 * If any part of the range between `start` and `end` is outside the bounds of
 * the async iterable, then that part is excluded from the returned async
 * iterable. Thus, the returned async iterable may be empty.
 *
 * WARNING: This function linearly iterates up to `end` because async iterables
 * do not support random access.
 *
 * @throws if either `start` or `end` is not a non-negative integer, or if
 * `start` is greater than `end`.
 *
 * @example
 * ```js
 * const asyncIterable = asAsync([`sloth`, `more sloth`, `even more sloth`])
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     sliceAsync(0, 3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     sliceAsync(0, 42),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     sliceAsync(1, 3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     sliceAsync(3, 5),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> []
 * ```
 *
 * @category Splices
 * @since v3.5.0
 */
declare const sliceAsync: {
  <Start extends number>(start: NonNegativeInteger<Start>): {
    <End extends number>(End: NonNegativeInteger<End>): <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
    <End extends number, Value>(End: NonNegativeInteger<End>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
  };
  <Start extends number, End extends number>(start: NonNegativeInteger<Start>, End: NonNegativeInteger<End>): <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>;
  <Start extends number, End extends number, Value>(start: NonNegativeInteger<Start>, End: NonNegativeInteger<End>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value>;
};

/**
 * Returns a concur iterable containing the values of `concurIterable` between
 * `start` and `end` (exclusive) of `concurIterable` in iteration order.
 *
 * If any part of the range between `start` and `end` is outside the bounds of
 * the concur iterable, then that part is excluded from the returned concur
 * iterable. Thus, the returned concur iterable may be empty.
 *
 * WARNING: This function linearly iterates up to `end` because concur iterables
 * do not support random access.
 *
 * @throws if either `start` or `end` is not a non-negative integer, or if
 * `start` is greater than `end`.
 *
 * @example
 * ```js
 * const concurIterable = asConcur([`sloth`, `more sloth`, `even more sloth`])
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     sliceConcur(0, 3),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     sliceConcur(0, 42),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     sliceConcur(1, 3),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'more sloth', 'even more sloth' ]
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     sliceConcur(3, 5),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> []
 * ```
 *
 * @category Splices
 * @since v3.5.0
 */
declare const sliceConcur: {
  <Start extends number>(start: NonNegativeInteger<Start>): {
    <End extends number>(End: NonNegativeInteger<End>): <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
    <End extends number, Value>(End: NonNegativeInteger<End>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
  };
  <Start extends number, End extends number>(start: NonNegativeInteger<Start>, End: NonNegativeInteger<End>): <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>;
  <Start extends number, End extends number, Value>(start: NonNegativeInteger<Start>, End: NonNegativeInteger<End>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value>;
};

/**
 * Returns an iterable containing the value at the given `index` of `iterable`
 * or an empty iterable if `index` is out of bounds.
 *
 * WARNING: This function linearly iterates up to `index` because iterables do
 * not support random access.
 *
 * @throws if `index` is not a non-negative integer.
 *
 * @example
 * ```js
 * const iterable = [`sloth`, `more sloth`, `even more sloth`]
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     at(1),
 *     get,
 *   ),
 * )
 * //=> 'more sloth'
 * ```
 *
 * @category Splices
 * @since v3.5.0
 */
declare const at: {
  <Index extends number>(index: NonNegativeInteger<Index>): <Value>(iterable: Iterable<Value>) => Optional<Value>;
  <Index extends number, Value>(index: NonNegativeInteger<Index>, iterable: Iterable<Value>): Optional<Value>;
};

/**
 * Returns an async iterable containing the value at the given `index` of
 * `asyncIterable` or an empty async iterable if `index` is out of bounds.
 *
 * WARNING: This function linearly iterates up to `index` because async
 * iterables do not support random access.
 *
 * @throws if `index` is not a non-negative integer.
 *
 * @example
 * ```js
 * const asyncIterable = asAsync([`sloth`, `more sloth`, `even more sloth`])
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     atAsync(1),
 *     getAsync,
 *   ),
 * )
 * //=> 'more sloth'
 * ```
 *
 * @category Splices
 * @since v3.5.0
 */
declare const atAsync: {
  <Index extends number>(index: NonNegativeInteger<Index>): <Value>(asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;
  <Index extends number, Value>(index: NonNegativeInteger<Index>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>;
};

/**
 * Returns a concur iterable containing the value at the given `index` of
 * `concurIterable` in iteration order, or an empty concur iterable if `index`
 * is out of bounds.
 *
 * WARNING: This function linearly iterates up to `index` because concur
 * iterables do not support random access.
 *
 * @throws if `index` is not a non-negative integer.
 *
 * @example
 * ```js
 * const concurIterable = asConcur([`sloth`, `more sloth`, `even more sloth`])
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     atConcur(1),
 *     getConcur,
 *   ),
 * )
 * //=> 'more sloth'
 * ```
 *
 * @category Splices
 * @since v3.5.0
 */
declare const atConcur: {
  <Index extends number>(index: NonNegativeInteger<Index>): <Value>(concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;
  <Index extends number, Value>(index: NonNegativeInteger<Index>, concurIterable: ConcurIterable<Value>): ConcurOptional<Value>;
};

/**
 * Returns an iterable equivalent to `iterable` except its values are grouped
 * into arrays that each contain `size` values.
 *
 * The last array in the returned iterable will contain fewer than `size` values
 * (but at least one) if the number of values in `iterable` is not divisible by
 * `size`.
 *
 * @throws if `size` is not a positive integer.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, 6, 7, 8, 9],
 *     chunk(3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
 *
 * console.log(
 *   pipe(
 *     [`S`, `L`, `O`, `T`, `H`],
 *     chunk(2),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ [ 'S', 'L' ], [ 'O', 'T' ], [ 'H' ] ]
 * ```
 *
 * @category Splices
 * @since v2.0.0
 */
declare const chunk: {
  <Size extends number>(size: PositiveInteger<Size>): <Value>(iterable: Iterable<Value>) => Iterable<Value[]>;
  <Size extends number, Value>(size: PositiveInteger<Size>, iterable: Iterable<Value>): Iterable<Value[]>;
};

/**
 * Returns an async iterable equivalent to `asyncIterable` except its values are
 * grouped into arrays that each contain `size` values.
 *
 * The last array in the returned async iterable will contain fewer than `size`
 * values (but at least one) if the number of values in `asyncIterable` is not
 * divisible by `size`.
 *
 * @throws if `size` is not a positive integer.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, 6, 7, 8, 9]),
 *     chunkAsync(3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
 *
 * console.log(
 *   await pipe(
 *     asAsync([`S`, `L`, `O`, `T`, `H`]),
 *     chunkAsync(2),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ [ 'S', 'L' ], [ 'O', 'T' ], [ 'H' ] ]
 * ```
 *
 * @category Splices
 * @since v2.0.0
 */
declare const chunkAsync: {
  <Size extends number>(size: PositiveInteger<Size>): <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value[]>;
  <Size extends number, Value>(size: PositiveInteger<Size>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value[]>;
};

/**
 * Returns a concur iterable equivalent to `concurIterable` except its values
 * are grouped into arrays that each contain `size` values.
 *
 * The last array in the returned concur iterable will contain fewer than `size`
 * values (but at least one) if the number of values in `concurIterable` is not
 * divisible by `size`.
 *
 * @throws if `size` is not a positive integer.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, 6, 7, 8, 9]),
 *     chunkConcur(3),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
 *
 * console.log(
 *   await pipe(
 *     asConcur([`S`, `L`, `O`, `T`, `H`]),
 *     chunkConcur(2),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ [ 'S', 'L' ], [ 'O', 'T' ], [ 'H' ] ]
 * ```
 *
 * @category Splices
 * @since v2.0.0
 */
declare const chunkConcur: {
  <Size extends number>(size: PositiveInteger<Size>): <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value[]>;
  <Size extends number, Value>(size: PositiveInteger<Size>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value[]>;
};

/**
 * Returns an iterable containing a rolling window of the values of `iterable`
 * as arrays of length `size`.
 *
 * @throws if `size` is not a positive integer.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, 6, `sloth`],
 *     window(3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ] ]
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, 6, `sloth`],
 *     window({ size: 3, partialStart: true }),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ] ]
 *
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, 6, `sloth`],
 *     window({ size: 3, partialStart: true, partialEnd: true }),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ], [ 6, 'sloth' ], [ 'sloth' ] ]
 * ```
 *
 * @category Splices
 * @since v2.0.0
 */
declare const window: {
  <Size extends number>(options: WindowOptions<Size>): <Value>(iterable: Iterable<Value>) => Iterable<Value[]>;
  <Size extends number, Value>(options: WindowOptions<Size>, iterable: Iterable<Value>): Iterable<Value[]>;
};

/**
 * Returns an async iterable containing a rolling window of the values of
 * `asyncIterable` as arrays of length `size`.
 *
 * @throws if `size` is not a positive integer.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, 6, `sloth`]),
 *     windowAsync(3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ] ]
 *
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, 6, `sloth`]),
 *     windowAsync({ size: 3, partialStart: true }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ] ]
 *
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, 6, `sloth`]),
 *     windowAsync({ size: 3, partialStart: true, partialEnd: true }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ], [ 6, 'sloth' ], [ 'sloth' ] ]
 * ```
 *
 * @category Splices
 * @since v2.0.0
 */
declare const windowAsync: {
  <Size extends number>(options: WindowOptions<Size>): <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value[]>;
  <Size extends number, Value>(options: WindowOptions<Size>, asyncIterable: AsyncIterable<Value>): AsyncIterable<Value[]>;
};

/**
 * Returns a concur iterable containing a rolling window of the values of
 * `concurIterable` as arrays of length `size`.
 *
 * @throws if `size` is not a positive integer.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, 6, `sloth`]),
 *     windowConcur(3),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ] ]
 *
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, 6, `sloth`]),
 *     windowConcur({ size: 3, partialStart: true }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ] ]
 *
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, 6, `sloth`]),
 *     windowConcur({ size: 3, partialStart: true, partialEnd: true }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ], [ 5, 6, 'sloth' ], [ 6, 'sloth' ], [ 'sloth' ] ]
 * ```
 *
 * @category Splices
 * @since v2.0.0
 */
declare const windowConcur: {
  <Size extends number>(options: WindowOptions<Size>): <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value[]>;
  <Size extends number, Value>(options: WindowOptions<Size>, concurIterable: ConcurIterable<Value>): ConcurIterable<Value[]>;
};

/**
 * Options for {@link window}, {@link windowAsync}, and {@link windowConcur}.
 *
 * @category Splices
 * @since v2.0.0
 */
type WindowOptions<Size extends number = number> = PositiveInteger<Size> | Readonly<{
  /**
   * The size of each window. Must be a positive integer.
   *
   * @since v2.0.0
   */
  size: PositiveInteger<Size>;

  /**
   * Whether the returned iterable should have partial windows at the start.
   * Defaults to `false`.
   *
   * @since v2.0.0
   */
  partialStart?: boolean;

  /**
   * Whether the returned iterable should have partial windows at the end.
   * Defaults to `false`.
   *
   * @since v2.0.0
   */
  partialEnd?: boolean;
}>;

/**
 * Returns an iterable that contains the values of each iterable in `iterables`
 * in iteration order.
 *
 * Like `Array.prototype.concat`, but for iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     concat([1, 2], [3, `sloth`, 5], [6, 7]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 'sloth', 5, 6, 7 ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const concat: <Value>(...iterables: readonly Iterable<Value>[]) => Iterable<Value>;

/**
 * Returns an async iterable that contains the values of each iterable in
 * `iterables` in iteration order.
 *
 * Like `Array.prototype.concat`, but for async iterables.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     concatAsync(asAsync([1, 2]), [3, `sloth`, 5], asAsync([6, 7])),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 'sloth', 5, 6, 7 ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const concatAsync: <Value>(...iterables: readonly (Iterable<Value> | AsyncIterable<Value>)[]) => AsyncIterable<Value>;

/**
 * Returns a concur iterable that contains the values of each iterable in
 * `iterables`.
 *
 * Like `Array.prototype.concat`, but for concur iterables.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     concatConcur(asAsync([1, 2]), [3, `sloth`, 5], asConcur([6, 7])),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 'sloth', 5, 6, 7 ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const concatConcur: <Value>(...iterables: readonly (Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>)[]) => ConcurIterable<Value>;

/**
 * Returns an iterable that pairs up same-index values from the given
 * `iterables` into tuples.
 *
 * The `iterables` are iterated in parallel until the shortest one is done, at
 * which point the returned iterable is done.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     zip(
 *      [1, 2, 3, 4],
 *      [5, `sloth`, 7],
 *      [8, 9, 10],
 *     ),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 5, 8 ], [ 2, 'sloth', 9 ], [ 3, 7, 10 ] ]
 * ```
 *
 * @category Splices
 * @since v3.8.0
 */
declare const zip: <Values extends unknown[] | []>(...iterables: Readonly<{ [Key in keyof Values]: Iterable<Values[Key]> }>) => Iterable<Values>;

/**
 * Returns an async iterable that pairs up same-index values from the given
 * `iterables` into tuples.
 *
 * The `iterables` are iterated in parallel until the shortest one is done, at
 * which point the returned async iterable is done.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     zipAsync(
 *      asAsync([1, 2, 3, 4]),
 *      [5, `sloth`, 7],
 *      asAsync([8, 9, 10]),
 *     ),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 5, 8 ], [ 2, 'sloth', 9 ], [ 3, 7, 10 ] ]
 * ```
 *
 * @category Splices
 * @since v3.8.0
 */
declare const zipAsync: <Values extends unknown[] | []>(...iterables: Readonly<{ [Key in keyof Values]: Iterable<Values[Key]> | AsyncIterable<Values[Key]> }>) => AsyncIterable<Values>;

/**
 * Returns a concur iterable that pairs up same-index values, in iteration
 * order, from the given `iterables` into tuples.
 *
 * The `iterables` are iterated in parallel until the shortest one is done, at
 * which point the returned concur iterable is done.
 *
 * WARNING: If one of the concur iterables yields values more quickly than
 * others, then an unbounded number of its values will be buffered so that they
 * can be yielded with the values of other concur iterables at the same index.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     zipConcur(
 *      asAsync([1, 2, 3, 4]),
 *      [5, `sloth`, 7],
 *      asConcur([8, 9, 10]),
 *     ),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ [ 1, 5, 8 ], [ 2, 'sloth', 9 ], [ 3, 7, 10 ] ]
 * ```
 *
 * @category Splices
 * @since v3.8.0
 */
declare const zipConcur: <Values extends unknown[] | []>(...iterables: Readonly<{ [Key in keyof Values]: Iterable<Values[Key]> | AsyncIterable<Values[Key]> | ConcurIterable<Values[Key]> }>) => ConcurIterable<Values>;
//#endregion
//#region src/operations/statistics.d.ts
/**
 * Returns a {@link Reducer} that counts the number of values it receives.
 *
 * Use when composing reducers. Prefer {@link count}, {@link countAsync}, and
 * {@link countConcur} for direct use on iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toCount(), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 2, 10 => 2 }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toCount: () => Reducer<unknown, number>;

/**
 * Returns the number of values in `iterable`.
 *
 * Like `Array.prototype.length`, but for iterables.
 *
 * @example
 * ```js
 * console.log(count([`sloth`, `more sloth`, `even more sloth`]))
 * //=> 3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const count: <Value>(iterable: Iterable<Value>) => number;

/**
 * Returns a promise that resolves to the number of values in `asyncIterable`.
 *
 * Like `Array.prototype.length`, but for async iterables.
 *
 * @example
 * ```js
 * console.log(
 *   await countAsync(asAsync([`sloth`, `more sloth`, `even more sloth`])),
 * )
 * //=> 3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const countAsync: <Value>(asyncIterable: AsyncIterable<Value>) => Promise<number>;

/**
 * Returns a promise that resolves to the number of values in `concurIterable`.
 *
 * Like `Array.prototype.length`, but for concur iterables.
 *
 * @example
 * ```js
 * console.log(
 *   await countConcur(asConcur([`sloth`, `more sloth`, `even more sloth`])),
 * )
 * //=> 3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const countConcur: <Value>(concurIterable: ConcurIterable<Value>) => Promise<number>;

/**
 * Returns a {@link Reducer} that sums the numbers it receives.
 *
 * Use when composing reducers. Prefer {@link sum}, {@link sumAsync}, and
 * {@link sumConcur} for direct use on iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string.length]),
 *     reduce(toGrouped(toSum(), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 10, 10 => 20 }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toSum: () => Reducer<number, number>;

/**
 * Returns the sum of the numbers of `iterable`.
 *
 * @example
 * ```js
 * console.log(sum([1, 4, 6, 2]))
 * //=> 13
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const sum: (iterable: Iterable<number>) => number;

/**
 * Returns a promise that resolves to the sum of the numbers of `asyncIterable`.
 *
 * @example
 * ```js
 * console.log(await sumAsync(asAsync([1, 4, 6, 2])))
 * //=> 3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const sumAsync: (asyncIterable: AsyncIterable<number>) => Promise<number>;

/**
 * Returns a promise that resolves to the sum of the numbers of
 * `concurIterable`.
 *
 * @example
 * ```js
 * console.log(await sumConcur(asConcur([1, 4, 6, 2])))
 * //=> 3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const sumConcur: (concurIterable: ConcurIterable<number>) => Promise<number>;

/**
 * Returns a {@link Reducer} that computes the mean of the numbers it receives.
 *
 * Use when composing reducers. Prefer {@link mean}, {@link meanAsync}, and
 * {@link meanConcur} for direct use on iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, [...string].filter(c => c === `o`).length]),
 *     reduce(toGrouped(toMean(), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 0.5, 10 => 2 }
 * ```
 *
 * @category Statistics
 * @since v3.5.0
 */
declare const toMean: () => Reducer<number, number>;

/**
 * Returns the mean of the numbers of `iterable`.
 *
 * Returns `NaN` for an empty iterable.
 *
 * @example
 * ```js
 * console.log(mean([1, 4, 6, 2]))
 * //=> 3.25
 *
 * console.log(mean([]))
 * //=> NaN
 * ```
 *
 * @category Statistics
 * @since v3.5.0
 */
declare const mean: (iterable: Iterable<number>) => number;

/**
 * Returns a promise that resolves to the mean of the numbers of
 * `asyncIterable`.
 *
 * Returns a promise that resolves to `NaN` for an empty async iterable.
 *
 * @example
 * ```js
 * console.log(await meanAsync(asAsync([1, 4, 6, 2])))
 * //=> 3.25
 *
 * console.log(await meanAsync(emptyAsync))
 * //=> NaN
 * ```
 *
 * @category Statistics
 * @since v3.5.0
 */
declare const meanAsync: (asyncIterable: AsyncIterable<number>) => Promise<number>;

/**
 * Returns a promise that resolves to the mean of the numbers of
 * `concurIterable`.
 *
 * Returns a promise that resolves to `NaN` for an empty concur iterable.
 *
 * @example
 * ```js
 * console.log(await meanConcur(asConcur([1, 4, 6, 2])))
 * //=> 3.25
 *
 * console.log(await meanConcur(emptyConcur))
 * //=> NaN
 * ```
 *
 * @category Statistics
 * @since v3.5.0
 */
declare const meanConcur: (concurIterable: ConcurIterable<number>) => Promise<number>;

/**
 * A function that compares two values of type `Value`.
 *
 * A return value:
 * - Less than zero implies `left < right`
 * - Equal to zero implies `left === right`
 * - Greater than zero implies `left > right`
 *
 * @category Statistics
 * @since v0.0.2
 */
type Compare<Value> = (left: Value, right: Value) => number;

/**
 * A function that compares two values of type `Value` possibly asynchronously.
 *
 * A return value that awaits to:
 * - Less than zero implies `left < right`
 * - Equal to zero implies `left === right`
 * - Greater than zero implies `left > right`
 *
 * @category Statistics
 * @since v0.0.2
 */
type AsyncCompare<Value> = (left: Value, right: Value) => MaybePromiseLike<number>;

/**
 * An object containing a minimum and maximum value.
 *
 * @category Statistics
 * @since v0.0.2
 */
type MinMax<Value> = {
  min: Value;
  max: Value;
};

/** @internal */
type ToMinOrMaxBy = <Value>(fn: Compare<Value>) => OptionalReducer<Value>;

/** @internal */
type MinOrMaxBy = {
  <Value>(fn: Compare<Value>, iterable: Iterable<Value>): Optional<Value>;
  <Value>(fn: Compare<Value>): (iterable: Iterable<Value>) => Optional<Value>;
};

/** @internal */
type ToMinOrMaxByAsync = <Value>(fn: AsyncCompare<Value>) => AsyncOptionalReducer<Value>;

/** @internal */
type MinOrMaxByAsync = {
  <Value>(fn: AsyncCompare<Value>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>;
  <Value>(fn: AsyncCompare<Value>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;
};

/** @internal */
type MinOrMaxByConcur = {
  <Value>(fn: AsyncCompare<Value>, concurIterable: ConcurIterable<Value>): ConcurOptional<Value>;
  <Value>(fn: AsyncCompare<Value>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;
};

/**
 * Returns an optional reducer that finds the minimum value of the values it
 * receives based on the `fn` {@link Compare} function.
 *
 * Use when composing reducers. Prefer {@link minBy} for direct use on
 * iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toMinBy((s1, s2) => s1.localeCompare(s2)), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 'sleep', 10 => 'more sloth' }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinBy: ToMinOrMaxBy;

/**
 * Returns an iterable containing a minimum value of `iterable` based on the
 * `fn` {@link Compare} function if `iterable` contains at least one value.
 * Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`eating`, `sleeping`, `yawning`],
 *     minBy((a, b) => a.length - b.length),
 *     get,
 *   ),
 * )
 * //=> eating
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minBy: MinOrMaxBy;

/**
 * Returns an async optional reducer that finds the minimum value of the values
 * it receives based on the `fn` {@link AsyncCompare} function.
 *
 * Use when composing reducers. Prefer {@link minByAsync} and
 * {@link minByConcur} for direct use on iterables.
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinByAsync: ToMinOrMaxByAsync;

/**
 * Returns an async iterable containing a minimum value of `asyncIterable` based
 * on the `fn` {@link AsyncCompare} function if `asyncIterable` contains at
 * least one value. Otherwise, returns an empty async iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`eating`, `sleeping`, `yawning`]),
 *     minByAsync((a, b) => a.length - b.length),
 *     getAsync,
 *   ),
 * )
 * //=> eating
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minByAsync: MinOrMaxByAsync;

/**
 * Returns a concur iterable containing a minimum value of `concurIterable`
 * based on the `fn` {@link AsyncCompare} function if `concurIterable` contains
 * at least one value. Otherwise, returns an empty concur iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`eating`, `sleeping`, `yawning`]),
 *     minByConcur((a, b) => a.length - b.length),
 *     getConcur,
 *   ),
 * )
 * //=> eating
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minByConcur: MinOrMaxByConcur;

/**
 * Returns an optional reducer that finds the maximum value of the values it
 * receives based on the `fn` {@link Compare} function.
 *
 * Use when composing reducers. Prefer {@link maxBy} for direct use on
 * iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toMaxBy((s1, s2) => s1.localeCompare(s2)), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 'sloth', 10 => 'some sloth' }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMaxBy: ToMinOrMaxBy;

/**
 * Returns an iterable containing a maximum value of `iterable` based on the
 * `fn` {@link Compare} function if `iterable` contains at least one value.
 * Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`eating`, `sleeping`, `yawning`],
 *     maxBy((a, b) => a.length - b.length),
 *     get,
 *   ),
 * )
 * //=> sleeping
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxBy: MinOrMaxBy;

/**
 * Returns an async optional reducer that finds the maximum value of the values
 * it receives based on the `fn` {@link AsyncCompare} function.
 *
 * Use when composing reducers. Prefer {@link maxByAsync} and
 * {@link maxByConcur} for direct use on iterables.
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMaxByAsync: ToMinOrMaxByAsync;

/**
 * Returns an async iterable containing a maximum value of `asyncIterable` based
 * on the `fn` {@link AsyncCompare} function if `asyncIterable` contains at
 * least one value. Otherwise, returns an empty async iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`eating`, `sleeping`, `yawning`]),
 *     maxByAsync((a, b) => a.length - b.length),
 *     getAsync,
 *   ),
 * )
 * //=> sleeping
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxByAsync: MinOrMaxByAsync;

/**
 * Returns a concur iterable containing a maximum value of `concurIterable`
 * based on the `fn` {@link AsyncCompare} function if `concurIterable` contains
 * at least one value. Otherwise, returns an empty concur iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`eating`, `sleeping`, `yawning`]),
 *     maxByConcur((a, b) => a.length - b.length),
 *     getConcur,
 *   ),
 * )
 * //=> sleeping
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxByConcur: MinOrMaxByConcur;

/**
 * Returns an optional reducer that finds the {@link MinMax} value of the values
 * it receives based on the `fn` {@link Compare} function.
 *
 * Use when composing reducers. Prefer {@link minMaxBy} for direct use on
 * iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toMinMaxBy((s1, s2) => s1.localeCompare(s2)), toMap())),
 *   ),
 * )
 * //=> Map(2) {
 * //=>   5 => { min: 'sleep', max: 'sloth' },
 * //=>   10 => { min: 'more sloth', max: 'some sloth' }
 * //=> }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinMaxBy: <Value>(fn: Compare<Value>) => OptionalReducer<MinMax<Value>>;

/**
 * Returns an iterable containing a {@link MinMax} value of `iterable` based on
 * the `fn` {@link Compare} function if `iterable` contains at least one value.
 * Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`eating`, `sleeping`, `yawning`],
 *     minMaxBy((a, b) => a.length - b.length),
 *     get,
 *   ),
 * )
 * //=> { min: 'eating', max: 'sleeping' }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMaxBy: {
  <Value>(fn: Compare<Value>, iterable: Iterable<Value>): Optional<MinMax<Value>>;
  <Value>(fn: Compare<Value>): (iterable: Iterable<Value>) => Optional<MinMax<Value>>;
};

/**
 * Returns an async optional reducer that finds the {@link MinMax} value of the
 * values it receives based on the `fn` {@link AsyncCompare} function.
 *
 * Use when composing reducers. Prefer {@link minMaxByAsync} and
 * {@link minMaxByConcur} for direct use on iterables.
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinMaxByAsync: <Value>(fn: AsyncCompare<Value>) => AsyncOptionalReducer<MinMax<Value>>;

/**
 * Returns an async iterable containing a {@link MinMax} value of
 * `asyncIterable` based on the `fn` {@link AsyncCompare} function if
 * `asyncIterable` contains at least one value. Otherwise, returns an empty
 * async iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`eating`, `sleeping`, `yawning`]),
 *     minMaxByAsync((a, b) => a.length - b.length),
 *     getAsync,
 *   ),
 * )
 * //=> { min: 'eating', max: 'sleeping' }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMaxByAsync: {
  <Value>(fn: AsyncCompare<Value>, asyncIterable: AsyncIterable<Value>): AsyncOptional<MinMax<Value>>;
  <Value>(fn: AsyncCompare<Value>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<MinMax<Value>>;
};

/**
 * Returns a concur iterable containing a {@link MinMax} value of
 * `concurIterable` based on the `fn` {@link AsyncCompare} function if
 * `concurIterable` contains at least one value. Otherwise, returns an empty
 * concur iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`eating`, `sleeping`, `yawning`]),
 *     minMaxByConcur((a, b) => a.length - b.length),
 *     getConcur,
 *   ),
 * )
 * //=> { min: 'eating', max: 'sleeping' }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMaxByConcur: {
  <Value>(fn: (left: Value, right: Value) => MaybePromiseLike<number>, concurIterable: ConcurIterable<Value>): ConcurOptional<MinMax<Value>>;
  <Value>(fn: (left: Value, right: Value) => MaybePromiseLike<number>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<MinMax<Value>>;
};

/** @internal */
type ToMinOrMaxWith = <Value>(fn: (value: Value) => number) => OptionalReducer<Value>;

/** @internal */
type MinOrMaxWith = {
  <Value>(fn: (value: Value) => number, iterable: Iterable<Value>): Optional<Value>;
  <Value>(fn: (value: Value) => number): (iterable: Iterable<Value>) => Optional<Value>;
};

/** @internal */
type ToMinOrMaxWithAsync = <Value>(fn: (value: Value) => MaybePromiseLike<number>) => AsyncOptionalReducer<Value>;

/** @internal */
type MinOrMaxWithAsync = {
  <Value>(fn: (value: Value) => MaybePromiseLike<number>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<number>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>;
};

/** @internal */
type MinOrMaxWithConcur = {
  <Value>(fn: (value: Value) => MaybePromiseLike<number>, concurIterable: ConcurIterable<Value>): ConcurOptional<Value>;
  <Value>(fn: (value: Value) => MaybePromiseLike<number>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<Value>;
};

/**
 * Returns an optional reducer that finds the minimum value of the values it
 * receives by comparing the numerical values of each value, as defined by `fn`.
 *
 * Use when composing reducers. Prefer {@link minWith} for direct use on
 * iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toMinWith(string => string.codePointAt(0)), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 'sloth', 10 => 'more sloth' }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinWith: ToMinOrMaxWith;

/**
 * Returns an iterable containing a minimum value of `iterable` by comparing the
 * numerical values of each value, as defined by `fn`, if `iterable` contains at
 * least one value. Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`eating`, `sleeping`, `yawning`],
 *     minWith(value => value.length),
 *     get,
 *   ),
 * )
 * //=> eating
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minWith: MinOrMaxWith;

/**
 * Returns an async optional reducer that finds the minimum value of the values
 * it receives by comparing the numerical values of each value, as defined by
 * `fn`.
 *
 * Use when composing reducers. Prefer {@link minWithAsync} and
 * {@link minWithConcur} for direct use on iterables.
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinWithAsync: ToMinOrMaxWithAsync;

/**
 * Returns an async iterable containing a minimum value of `asyncIterable` by
 * comparing the numerical values of each value, as defined by `fn`, if
 * `asyncIterable` contains at least one value. Otherwise, returns an empty
 * async iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`eating`, `sleeping`, `yawning`]),
 *     minWithAsync(value => value.length),
 *     getAsync,
 *   ),
 * )
 * //=> eating
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minWithAsync: MinOrMaxWithAsync;

/**
 * Returns a concur iterable containing a minimum value of `concurIterable` by
 * comparing the numerical values of each value, as defined by `fn`, if
 * `concurIterable` contains at least one value. Otherwise, returns an empty
 * concur iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`eating`, `sleeping`, `yawning`]),
 *     minWithConcur(value => value.length),
 *     getConcur,
 *   ),
 * )
 * //=> eating
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minWithConcur: MinOrMaxWithConcur;

/**
 * Returns an optional reducer that finds the maximum value of the values it
 * receives by comparing the numerical values of each value, as defined by `fn`.
 *
 * Use when composing reducers. Prefer {@link maxWith} for direct use on
 * iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toMaxWith(string => string.codePointAt(0)), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 'sloth', 10 => 'some sloth' }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMaxWith: ToMinOrMaxWith;

/**
 * Returns an iterable containing a maximum value of `iterable` by comparing the
 * numerical values of each value, as defined by `fn`, if `iterable` contains at
 * least one value. Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`eating`, `sleeping`, `yawning`],
 *     maxWith(value => value.length),
 *     get,
 *   ),
 * )
 * //=> sleeping
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxWith: MinOrMaxWith;

/**
 * Returns an async optional reducer that finds the maximum value of the values
 * it receives by comparing the numerical values of each value, as defined by
 * `fn`.
 *
 * Use when composing reducers. Prefer {@link maxWithAsync} and
 * {@link maxWithConcur} for direct use on iterables.
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMaxWithAsync: ToMinOrMaxWithAsync;

/**
 * Returns an async iterable containing a maximum value of `asyncIterable` by
 * comparing the numerical values of each value, as defined by `fn`, if
 * `asyncIterable` contains at least one value. Otherwise, returns an empty
 * async iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`eating`, `sleeping`, `yawning`]),
 *     maxWithAsync(value => value.length),
 *     getAsync,
 *   ),
 * )
 * //=> sleeping
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxWithAsync: MinOrMaxWithAsync;

/**
 * Returns a concur iterable containing a maximum value of `concurIterable` by
 * comparing the numerical values of each value, as defined by `fn`, if
 * `concurIterable` contains at least one value. Otherwise, returns an empty
 * concur iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`eating`, `sleeping`, `yawning`]),
 *     maxWithConcur(value => value.length),
 *     getConcur,
 *   ),
 * )
 * //=> sleeping
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxWithConcur: MinOrMaxWithConcur;

/**
 * Returns an optional reducer that finds the {@link MinMax} value of the values
 * it receives by comparing the numerical values of each value, as defined by
 * `fn`.
 *
 * Use when composing reducers. Prefer {@link minMaxWith} for direct use on
 * iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toMinMaxWith(string => string.codePointAt(0)), toMap())),
 *   ),
 * )
 * //=> Map(2) {
 * //=>   5 => { min: 'sloth', max: 'sloth' },
 * //=>   10 => { min: 'more sloth', max: 'some sloth' }
 * //=> }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinMaxWith: <Value>(fn: (value: Value) => number) => OptionalReducer<MinMax<Value>>;

/**
 * Returns an iterable containing a {@link MinMax} value of `iterable` by
 * comparing the numerical values of each value, as defined by `fn`, if
 * `iterable` contains at least one value. Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`eating`, `sleeping`, `yawning`],
 *     minMaxWith(value => value.length),
 *     get,
 *   ),
 * )
 * //=> { min: 'eating', max: 'sleeping' }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMaxWith: {
  <Value>(fn: (value: Value) => number, iterable: Iterable<Value>): Optional<MinMax<Value>>;
  <Value>(fn: (value: Value) => number): (iterable: Iterable<Value>) => Optional<MinMax<Value>>;
};

/**
 * Returns an async optional reducer that finds the {@link MinMax} value of the
 * values it receives by comparing the numerical values of each value, as
 * defined by `fn`.
 *
 * Use when composing reducers. Prefer {@link minMaxWithAsync} and
 * {@link minMaxWithConcur} for direct use on iterables.
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinMaxWithAsync: <Value>(fn: (value: Value) => MaybePromiseLike<number>) => AsyncOptionalReducer<MinMax<Value>>;

/**
 * Returns an async iterable containing a {@link MinMax} value of
 * `asyncIterable` by comparing the numerical values of each value, as defined
 * by `fn`, if `asyncIterable` contains at least one value. Otherwise, returns
 * an empty async iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`eating`, `sleeping`, `yawning`]),
 *     minMaxWithAsync(value => value.length),
 *     getAsync,
 *   ),
 * )
 * //=> { min: 'eating', max: 'sleeping' }
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minMaxWithAsync: {
  <Value>(fn: (value: Value) => MaybePromiseLike<number>, asyncIterable: AsyncIterable<Value>): AsyncOptional<MinMax<Value>>;
  <Value>(fn: (value: Value) => MaybePromiseLike<number>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<MinMax<Value>>;
};

/**
 * Returns a concur iterable containing a {@link MinMax} value of
 * `concurIterable` by comparing the numerical values of each value, as defined
 * by `fn`, if `concurIterable` contains at least one value. Otherwise, returns
 * an empty concur iterable.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`eating`, `sleeping`, `yawning`]),
 *     minMaxWithConcur(value => value.length),
 *     getConcur,
 *   ),
 * )
 * //=> { min: 'eating', max: 'sleeping' }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMaxWithConcur: {
  <Value>(fn: (value: Value) => MaybePromiseLike<number>, concurIterable: ConcurIterable<Value>): ConcurOptional<MinMax<Value>>;
  <Value>(fn: (value: Value) => MaybePromiseLike<number>): (concurIterable: ConcurIterable<Value>) => ConcurOptional<MinMax<Value>>;
};

/**
 * Returns an optional reducer that finds the minimum value of the values it
 * receives.
 *
 * Use when composing reducers. Prefer {@link min} for direct use on iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string.codePointAt(0)]),
 *     reduce(toGrouped(toMin(), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 115, 10 => 109 }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMin: () => OptionalReducer<number>;

/**
 * Returns an iterable containing a minimum value of `iterable` if `iterable`
 * contains at least one value. Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(pipe([4, 1, 5, -3], min, get))
 * //=> -3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const min: (iterable: Iterable<number>) => Optional<number>;

/**
 * Returns an async iterable containing a minimum value of `asyncIterable` if
 * `asyncIterable` contains at least one value. Otherwise, returns an empty
 * async iterable.
 *
 * @example
 * ```js
 * console.log(await pipe(asAsync([4, 1, 5, -3]), minAsync, getAsync))
 * //=> -3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minAsync: (asyncIterable: AsyncIterable<number>) => AsyncOptional<number>;

/**
 * Returns a concur iterable containing a minimum value of `concurIterable` if
 * `concurIterable` contains at least one value. Otherwise, returns an empty
 * concur iterable.
 *
 * @example
 * ```js
 * console.log(await pipe(asConcur([4, 1, 5, -3]), minConcur, getConcur))
 * //=> -3
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const minConcur: (concurIterable: ConcurIterable<number>) => ConcurOptional<number>;

/**
 * Returns an optional reducer that finds the maximum value of the values it
 * receives.
 *
 * Use when composing reducers. Prefer {@link max} for direct use on iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string.codePointAt(0)]),
 *     reduce(toGrouped(toMax(), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 115, 10 => 115 }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMax: () => OptionalReducer<number>;

/**
 * Returns an iterable containing a maximum value of `iterable` if `iterable`
 * contains at least one value. Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(pipe([4, 1, 5, -3], max, get))
 * //=> 5
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const max: (iterable: Iterable<number>) => Optional<number>;

/**
 * Returns an async iterable containing a maximum value of `asyncIterable` if
 * `asyncIterable` contains at least one value. Otherwise, returns an empty
 * async iterable.
 *
 * @example
 * ```js
 * console.log(await pipe(asAsync([4, 1, 5, -3]), maxAsync, getAsync))
 * //=> 5
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxAsync: (asyncIterable: AsyncIterable<number>) => AsyncOptional<number>;

/**
 * Returns a concur iterable containing a maximum value of `concurIterable` if
 * `concurIterable` contains at least one value. Otherwise, returns an empty
 * concur iterable.
 *
 * @example
 * ```js
 * console.log(await pipe(asConcur([4, 1, 5, -3]), maxConcur, getConcur))
 * //=> 5
 * ```
 *
 * @category Statistics
 * @since v0.0.1
 */
declare const maxConcur: (concurIterable: ConcurIterable<number>) => ConcurOptional<number>;

/**
 * Returns an optional reducer that finds the {@link MinMax} value of the values
 * it receives.
 *
 * Use when composing reducers. Prefer {@link minMax} for direct use on
 * iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string.codePointAt(0)]),
 *     reduce(toGrouped(toMinMax(), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => { min: 115, max: 115 }, 10 => { min: 109, max: 115 } }
 * ```
 *
 * @category Statistics
 * @since v2.0.0
 */
declare const toMinMax: () => OptionalReducer<MinMax<number>>;

/**
 * Returns an iterable containing a {@link MinMax} value of `iterable` if
 * `iterable` contains at least one value. Otherwise, returns an empty iterable.
 *
 * @example
 * ```js
 * console.log(pipe([4, 1, 5, -3], minMax, get))
 * //=> { min: -3, max: 5 }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMax: (iterable: Iterable<number>) => Optional<MinMax<number>>;

/**
 * Returns an async iterable containing a {@link MinMax} value of
 * `asyncIterable` if `asyncIterable` contains at least one value. Otherwise,
 * returns an empty async iterable.
 *
 * @example
 * ```js
 * console.log(await pipe(asAsync([4, 1, 5, -3]), minMaxAsync, getAsync))
 * //=> { min: -3, max: 5 }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMaxAsync: (asyncIterable: AsyncIterable<number>) => AsyncOptional<MinMax<number>>;

/**
 * Returns a concur iterable containing a {@link MinMax} value of
 * `concurIterable` if `concurIterable` contains at least one value. Otherwise,
 * returns an empty concur iterable.
 *
 * @example
 * ```js
 * console.log(await pipe(asConcur([4, 1, 5, -3]), minMaxConcur, getConcur))
 * //=> { min: -3, max: 5 }
 * ```
 *
 * @category Statistics
 * @since v0.0.2
 */
declare const minMaxConcur: (concurIterable: ConcurIterable<number>) => ConcurOptional<MinMax<number>>;
//#endregion
//#region src/operations/transforms.d.ts
/**
 * Returns an iterable containing the values of `iterable` transformed by `fn`
 * in iteration order.
 *
 * Like `Array.prototype.map`, but for iterables.
 *
 * @example
 * ```js playground
 * import { map, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     map(word => word.length),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 5, 4, 5 ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const map: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => To): (iterable: Iterable<From>) => Iterable<To>;
  <From, To extends unknown[] | []>(fn: (value: From) => To, iterable: Iterable<From>): Iterable<To>;
  <From, To>(fn: (value: From) => To): (iterable: Iterable<From>) => Iterable<To>;
  <From, To>(fn: (value: From) => To, iterable: Iterable<From>): Iterable<To>;
};

/**
 * Returns an async iterable containing the values of `asyncIterable`
 * transformed by `fn` in iteration order.
 *
 * Like `Array.prototype.map`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, mapAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const mapAsync: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To>): (asyncIterable: AsyncIterable<From>) => AsyncIterable<To>;
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To>, asyncIterable: AsyncIterable<From>): AsyncIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>): (asyncIterable: AsyncIterable<From>) => AsyncIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>, asyncIterable: AsyncIterable<From>): AsyncIterable<To>;
};

/**
 * Returns a concur iterable containing the values of `concurIterable`
 * transformed by `fn` in iteration order.
 *
 * Like `Array.prototype.map`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { asConcur, mapConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const mapConcur: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To>): (concurIterable: ConcurIterable<From>) => ConcurIterable<To>;
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<To>, concurIterable: ConcurIterable<From>): ConcurIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>): (concurIterable: ConcurIterable<From>) => ConcurIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<To>, concurIterable: ConcurIterable<From>): ConcurIterable<To>;
};

/**
 * Returns an iterable containing the values of the iterables returned from
 * applying `fn` to each value of `iterable` in iteration order.
 *
 * Like `Array.prototype.flatMap`, but for iterables.
 *
 * @example
 * ```js playground
 * import { flatMap, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     flatMap(word => [word, `much ${word}`]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [
 * //=>   'sloth',
 * //=>   'much sloth',
 * //=>   'lazy',
 * //=>   'much lazy',
 * //=>   'sleep',
 * //=>   'much sleep'
 * //=> ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const flatMap: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => Iterable<To>): (iterable: Iterable<From>) => Iterable<To>;
  <From, To extends unknown[] | []>(fn: (value: From) => Iterable<To>, iterable: Iterable<From>): Iterable<To>;
  <From, To>(fn: (value: From) => Iterable<To>): (iterable: Iterable<From>) => Iterable<To>;
  <From, To>(fn: (value: From) => Iterable<To>, iterable: Iterable<From>): Iterable<To>;
};

/**
 * Returns an async iterable containing the values of the async iterables
 * returned, or resolving from promises returned, from applying `fn` to each
 * value of `asyncIterable` in iteration order.
 *
 * Like `Array.prototype.flatMap`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, flatMapAsync, map, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     flatMapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'adjective',
 * //=>   'verb'
 * //=> ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const flatMapAsync: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To>>): (asyncIterable: AsyncIterable<From>) => AsyncIterable<To>;
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To>>, asyncIterable: AsyncIterable<From>): AsyncIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To>>): (asyncIterable: AsyncIterable<From>) => AsyncIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To>>, asyncIterable: AsyncIterable<From>): AsyncIterable<To>;
};

/**
 * Returns an concur iterable containing the values of the concur iterables
 * returned, or resolving from promises returned, from applying `fn` to each
 * value of `concurIterable`.
 *
 * Like `Array.prototype.flatMap`, but for concur iterables.
 *
 * @example
 * ```js playground
 * import { asConcur, flatMapConcur, map, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     flatMapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> [
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'adjective',
 * //=>   'verb'
 * //=> ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const flatMapConcur: {
  // These overloads help with inferring tuple types returned from the callback.
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To> | ConcurIterable<To>>): (concurIterable: ConcurIterable<From>) => ConcurIterable<To>;
  <From, To extends unknown[] | []>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To> | ConcurIterable<To>>, concurIterable: ConcurIterable<From>): ConcurIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To> | ConcurIterable<To>>): (concurIterable: ConcurIterable<From>) => ConcurIterable<To>;
  <From, To>(fn: (value: From) => MaybePromiseLike<Iterable<To> | AsyncIterable<To> | ConcurIterable<To>>, concurIterable: ConcurIterable<From>): ConcurIterable<To>;
};

/**
 * Returns an iterable that contains the values of each iterable in `iterable`
 * in iteration order.
 *
 * Like `Array.prototype.flat`, but for iterables.
 *
 * @example
 * ```js playground
 * import { flatten, pipe, reduce, toArray } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [[`sloth`, `lazy`], [`sleep`]],
 *     flatten,
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'lazy', 'sleep' ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const flatten: <Value>(iterable: Iterable<Iterable<Value>>) => Iterable<Value>;

/**
 * Returns an async iterable that contains the values of each iterable in
 * `asyncIterable` in iteration order.
 *
 * Like `Array.prototype.flat`, but for async iterables.
 *
 * @example
 * ```js playground
 * import { asAsync, flattenAsync, map, mapAsync, pipe, reduceAsync, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     flattenAsync,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'adjective',
 * //=>   'verb'
 * //=> ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const flattenAsync: <Value>(asyncIterable: AsyncIterable<Iterable<Value> | AsyncIterable<Value>>) => AsyncIterable<Value>;

/**
 * Returns a concur iterable that contains the values of each iterable in
 * `concurIterable`.
 *
 * Like `Array.prototype.flat`, but for concur iterables.
 *
 * Unlike {@link flatten} and {@link flattenAsync}, this function does not
 * necessarily iterate over each iterable in sequence.
 *
 * @example
 * ```js playground
 * import { asConcur, flattenConcur, map, mapConcur, pipe, reduceConcur, toArray } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       const [{ meanings }] = await response.json()
 *       return map(meaning => meaning.partOfSpeech, meanings)
 *     }),
 *     flattenConcur,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> [
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'noun',
 * //=>   'verb',
 * //=>   'adjective',
 * //=>   'verb'
 * //=> ]
 * ```
 *
 * @category Transforms
 * @since v0.0.1
 */
declare const flattenConcur: <Value>(concurIterable: ConcurIterable<Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>>) => ConcurIterable<Value>;

/**
 * Returns an iterable equivalent to `iterable` except each value of `iterable`
 * is placed in an entry containing the value's 0-based index in the iteration
 * order followed by the value itself.
 *
 * @example
 * ```js playground
 * import { index, join, map, pipe, reduce } from 'lfi'
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `lazy`, `sleep`],
 *     index,
 *     map(([index, word]) => `${index + 1}. ${word}`),
 *     join(`\n`),
 *   ),
 * )
 * //=> 1. sloth
 * //=> 2. lazy
 * //=> 3. sleep
 * ```
 *
 * @category Transforms
 * @since v2.0.0
 */
declare const index: <Value>(iterable: Iterable<Value>) => Iterable<[number, Value]>;

/**
 * Returns an async iterable equivalent to `asyncIterable` except each value of
 * `asyncIterable` is placed in an entry containing the value's 0-based index in
 * the iteration order followed by the value itself.
 *
 * @example
 * ```js playground
 * import { asAsync, indexAsync, joinAsync, mapAsync, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `lazy`, `sleep`]),
 *     mapAsync(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     indexAsync,
 *     mapAsync(([index, word]) => `${index + 1}. ${word}`),
 *     joinAsync(`\n`),
 *   ),
 * )
 * //=> 1. /slɑθ/
 * //=> 2. /ˈleɪzi/
 * //=> 3. /sliːp/
 * ```
 *
 * @category Transforms
 * @since v2.0.0
 */
declare const indexAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<[number, Value]>;

/**
 * Returns a concur iterable equivalent to `concurIterable` except each value of
 * `concurIterable` is placed in an entry containing the value's 0-based index
 * in the iteration order followed by the value itself.
 *
 * @example
 * ```js playground
 * import { asConcur, indexConcur, joinConcur, mapConcur, pipe } from 'lfi'
 *
 * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
 *
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `lazy`, `sleep`]),
 *     mapConcur(async word => {
 *       const response = await fetch(`${API_URL}/${word}`)
 *       return (await response.json())[0].phonetic
 *     }),
 *     indexConcur,
 *     mapConcur(([index, word]) => `${index + 1}. ${word}`),
 *     joinConcur(`\n`),
 *   ),
 * )
 * // NOTE: This order may change between runs
 * //=> 1. /slɑθ/
 * //=> 2. /ˈleɪzi/
 * //=> 3. /sliːp/
 * ```
 *
 * @category Transforms
 * @since v2.0.0
 */
declare const indexConcur: <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<[number, Value]>;
//#endregion
export { AsAsyncOptions, AsyncCompare, AsyncFunctionReducer, AsyncKeyedReducer, AsyncOptional, AsyncOptionalReducer, AsyncReducer, BackpressureStrategy, Compare, ConcurIterable, ConcurIterableApply, ConcurOptional, FunctionReducer, KeyedReducer, MinMax, NO_ENTRY, Optional, OptionalReducer, RangeIterable, RawAsyncKeyedReducer, RawAsyncOptionalReducerWithFinish, RawAsyncOptionalReducerWithoutFinish, RawAsyncReducerWithFinish, RawAsyncReducerWithoutFinish, RawKeyedReducer, RawOptionalReducerWithFinish, RawOptionalReducerWithoutFinish, RawReducerWithFinish, RawReducerWithoutFinish, Reducer, WindowOptions, all, allAsync, allConcur, any, anyAsync, anyConcur, asAsync, asConcur, at, atAsync, atConcur, cache, cacheAsync, cacheConcur, chunk, chunkAsync, chunkConcur, compose, concat, concatAsync, concatConcur, concurIteratorSymbol, consume, consumeAsync, consumeConcur, count, countAsync, countConcur, curry, cycle, cycleAsync, drop, dropAsync, dropConcur, dropWhile, dropWhileAsync, dropWhileConcur, each, eachAsync, eachConcur, empty, emptyAsync, emptyConcur, entries, exclude, excludeAsync, excludeConcur, filter, filterAsync, filterConcur, filterMap, filterMapAsync, filterMapConcur, find, findAsync, findConcur, findLast, findLastAsync, findLastConcur, first, firstAsync, firstConcur, flatMap, flatMapAsync, flatMapConcur, flatten, flattenAsync, flattenConcur, forEach, forEachAsync, forEachConcur, generate, generateAsync, get, getAsync, getConcur, includes, includesAsync, includesConcur, index, indexAsync, indexConcur, join, joinAsync, joinConcur, keys, last, lastAsync, lastConcur, map, mapAsync, mapAsyncReducer, mapConcur, mapReducer, max, maxAsync, maxBy, maxByAsync, maxByConcur, maxConcur, maxWith, maxWithAsync, maxWithConcur, mean, meanAsync, meanConcur, min, minAsync, minBy, minByAsync, minByConcur, minConcur, minMax, minMaxAsync, minMaxBy, minMaxByAsync, minMaxByConcur, minMaxConcur, minMaxWith, minMaxWithAsync, minMaxWithConcur, minWith, minWithAsync, minWithConcur, next, nextAsync, none, noneAsync, noneConcur, normalizeReducer, opaque, opaqueAsync, opaqueConcur, or, orAsync, orConcur, pipe, rangeTo, rangeUntil, reduce, reduceAsync, reduceConcur, repeat, slice, sliceAsync, sliceConcur, sum, sumAsync, sumConcur, take, takeAsync, takeConcur, takeWhile, takeWhileAsync, takeWhileConcur, toArray, toCount, toGrouped, toJoin, toMap, toMax, toMaxBy, toMaxByAsync, toMaxWith, toMaxWithAsync, toMean, toMin, toMinBy, toMinByAsync, toMinMax, toMinMaxBy, toMinMaxByAsync, toMinMaxWith, toMinMaxWithAsync, toMinWith, toMinWithAsync, toMultiple, toObject, toSet, toSum, toWeakMap, toWeakSet, unique, uniqueAsync, uniqueBy, uniqueByAsync, uniqueByConcur, uniqueConcur, values, window, windowAsync, windowConcur, zip, zipAsync, zipConcur };