/** @internal */
type MaybePromiseLike<Value> = Value | PromiseLike<Value>

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

/** @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>>
>

/** @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 version of `fn`.
 *
 * @example
 * ```js
 * 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
 * console.log(
 *   pipe(
 *     `sloth`,
 *     name => `${name.toUpperCase()}!`,
 *     text => [text, text, text],
 *     array => array.join(` `),
 *   ),
 * )
 * // => SLOTH! SLOTH! SLOTH!
 * ```
 *
 * @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
}

/**
 * Returns a function that takes a single parameter and pipes it through the
 * given functions.
 *
 * @example
 * ```js
 * const screamify = compose(
 *   name => `${name.toUpperCase()}!`,
 *   text => [text, text, text],
 *   array => array.join(` `),
 * )
 *
 * console.log(screamify(`sloth`))
 * // => SLOTH! SLOTH! SLOTH!
 * ```
 *
 * @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
}

/**
 * Returns an async iterable wrapper around `iterable`.
 *
 * Note that when passing a concur iterable the returned async iterable may have
 * to buffer the values produced by the concur iterable because values may not
 * be read from the async iterable as quickly as they are produced by the concur
 * iterable. This is a fundamental problem because concur iterables are "push"
 * based while async iterables are "pull" based, which creates backpressure.
 *
 * @example
 * ```js
 * const asyncIterable = asAsync([`sloth`, `more sloth`, `even more sloth`])
 *
 * console.log(typeof asyncIterable[Symbol.asyncIterator])
 * //=> function
 *
 * for await (const value of asyncIterable) {
 *   console.log(value)
 * }
 * //=> sloth
 * //=> more sloth
 * //=> even more sloth
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
declare const asAsync: <Value>(
  iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>,
) => AsyncIterable<Value>

/**
 * Represents a potentially lazy collection of values, each of type `Value`,
 * that can be iterated over concurrently.
 *
 * The collection can be iterated by invoking the concur iterable with an
 * `apply` callback. The callback is applied to each value in the collection,
 * potentially asynchronously, in some order.
 *
 * Invoking the concur iterable 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.
 *
 * It is like an event emitter that accepts only one event handler and returns a
 * promise that resolves when all events have been emitted and handled.
 *
 * @example
 * ```js
 * const slothNamesConcurIterable = pipe(
 *   asConcur(['sloth-names1.txt', 'sloth-names2.txt']),
 *   mapConcur(filename => fs.promises.readFile(filename, `utf8`)),
 *   flatMapConcur(content => content.split(`\n`)),
 * )
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
type ConcurIterable<Value> = (
  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
 * const concurIterable = asConcur([`sloth`, `more sloth`, `even more sloth`])
 *
 * await forEachConcur(console.log, concurIterable)
 * //=> sloth
 * //=> more sloth
 * //=> even more sloth
 * ```
 *
 * @category Core
 * @since v0.0.2
 */
declare const asConcur: <Value>(
  iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>,
) => ConcurIterable<Value>

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

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

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

/**
 * Returns an iterable equivalent, but not referentially equal, to `iterable`.
 *
 * @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`.
 *
 * @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`.
 *
 * @category Core
 * @since v2.0.0
 */
declare const opaqueConcur: <Value>(
  concurIterable: ConcurIterable<Value>,
) => ConcurIterable<Value>

/**
 * 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
 * console.log(pipe([`sloth`], or(() => `Never called`)))
 * //=> sloth
 *
 * console.log(pipe([], or(() => `I get called!`)))
 * //=> I get called!
 *
 * console.log(pipe([1, `sloth`, 3], or(() => `I also get called!`)))
 * //=> I also get 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
 * console.log(await pipe(asAsync([`sloth`]), orAsync(() => `Never called`)))
 * //=> sloth
 *
 * console.log(await pipe(emptyAsync, orAsync(() => `I get called!`)))
 * //=> I get called!
 *
 * console.log(
 *   await pipe(
 *     asAsync([1, `sloth`, 3]),
 *     orAsync(() => `I also get called!`),
 *   ),
 * )
 * //=> I also get called!
 * ```
 *
 * @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`.
 *
 * @example
 * ```js
 * console.log(await pipe(asConcur([`sloth`]), orConcur(() => `Never called`)))
 * //=> sloth
 *
 * console.log(await pipe(emptyConcur, orConcur(() => `I get called!`)))
 * //=> I get called!
 *
 * console.log(
 *   await pipe(
 *     asConcur([1, `sloth`, 3]),
 *     orConcur(() => `I also get called!`),
 *   ),
 * )
 * //=> I also get called!
 * ```
 *
 * @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
 * 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([1, `sloth`, 3]))
 * } 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
 * console.log(await getAsync(asAsync([`sloth`])))
 * //=> sloth
 *
 * try {
 *   console.log(await getAsync(emptyAsync))
 * } catch {
 *   console.log(`Oh no! It was empty...`)
 * }
 * //=> Oh no! It was empty...
 *
 * try {
 *   console.log(await getAsync(asAsync([1, `sloth`, 3])))
 * } 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 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.
 *
 * @example
 * ```js
 * console.log(await getConcur(asConcur([`sloth`])))
 * //=> sloth
 *
 * try {
 *   console.log(await getConcur(emptyConcur))
 * } catch {
 *   console.log(`Oh no! It was empty...`)
 * }
 * //=> Oh no! It was empty...
 *
 * try {
 *   console.log(await getConcur(asConcur([1, `sloth`, 3])))
 * } catch {
 *   console.log(`Oh no! It had more than one value...`)
 * }
 * //=> Oh no! It had more than one value...
 * ```
 *
 * @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
 * const slothActivities = [`sleeping`, `yawning`, `eating`]
 * const [first, rest] = next(slothActivities)
 *
 * console.log(get(first))
 * //=> sleeping
 *
 * console.log([...rest])
 * //=> [ 'yawning', 'eating' ]
 *
 * const badThingsAboutSloths = []
 * const [first2, rest2] = next(badThingsAboutSloths)
 *
 * 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
 * const slothActivities = asAsync([`sleeping`, `yawning`, `eating`])
 * const [first, rest] = await nextAsync(slothActivities)
 *
 * console.log(await getAsync(first))
 * //=> sleeping
 *
 * console.log(await reduceAsync(toArray(), rest))
 * //=> [ 'yawning', 'eating' ]
 *
 * const badThingsAboutSloths = emptyAsync
 * const [first2, rest2] = await nextAsync(badThingsAboutSloths)
 *
 * 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>]>

/**
 * A reducer that reduces by combining pairs of values using function
 * application.
 *
 * @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}.
 *
 * @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 RawOptionalReducerWithFinish.add} and then tranforming the final value
 * using {@link RawOptionalReducerWithFinish.finish}.
 *
 * @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 OptionalReducer.add} and then tranforming the final value using
 * {@link OptionalReducer.finish}.
 *
 * @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}.
 *
 * @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 RawReducerWithFinish.create}, then adding values to the accumulator
 * values using {@link RawReducerWithFinish.add}, and then tranforming the final
 * accumulator using {@link RawReducerWithFinish.finish}.
 *
 * @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 Reducer.create}, then adding values to the accumulator values using
 * {@link Reducer.add}, and then tranforming the final accumulator using
 * {@link Reducer.finish}.
 *
 * @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 RawKeyedReducer.create} and then adding key-value pairs to the
 * accumulator values using {@link RawKeyedReducer.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 KeyedReducer.create} and then adding key-value pairs to the
 * accumulator values using {@link KeyedReducer.add}. The accumulator can be
 * queried for values by key using {@link KeyedReducer.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 RawAsyncOptionalReducerWithFinish.add} and then tranforming 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 AsyncOptionalReducer.add} and then tranforming the final value using
 * {@link AsyncOptionalReducer.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 RawAsyncReducerWithFinish.create}, then adding values to the
 * accumulator values using {@link RawAsyncReducerWithFinish.add}, and then
 * tranforming the final accumulator using
 * {@link RawAsyncReducerWithFinish.finish}. The async
 * reducer is optionally able to combine pairs of accumulators using
 * {@link RawAsyncReducerWithFinish.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 AsyncReducer.create}, then adding values to the accumulator values
 * using {@link AsyncReducer.add}, and then tranforming the final accumulator
 * using {@link AsyncReducer.finish}. The async reducer is optionally able to
 * combine pairs of accumulators using {@link AsyncReducer.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 RawAsyncKeyedReducer.create} and then adding key-value pairs to the
 * accumulator values using {@link RawAsyncKeyedReducer.add}. The async keyed
 * reducer is optionally able to combine pairs of accumulators using
 * {@link RawAsyncKeyedReducer.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 AsyncKeyedReducer.create} and then adding key-value pairs to the
 * accumulator values using {@link AsyncKeyedReducer.add}. The async keyed
 * reducer is optionally able to combine pairs of accumulators using
 * {@link AsyncKeyedReducer.combine}. The accumulator can be queried for values
 * by key using {@link AsyncKeyedReducer.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 Reducer.create}. Then each
 * value in `iterable` is added to the accumulator and the current accumulator
 * is updated using {@link Reducer.add}. Finally, the resulting accumulator is
 * transformed using {@link Reducer.finish} if specified.
 *
 * If `reducer` is an optional reducer (no {@link Reducer.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
 * console.log(
 *   pipe(
 *     [`Hello`, `Sloth!`, `What`, `an`, `interesting`, `program!`],
 *     reduce((a, b) => `${a} ${b}`),
 *     get,
 *   ),
 * )
 * //=> Hello Sloth! What an interesting program!
 *
 * console.log(
 *   pipe(
 *     [`Hello`, `Sloth!`, `What`, `an`, `interesting`, `program!`],
 *     reduce({ create: () => ``, add: (a, b) => `${a} ${b}` }),
 *   ),
 * )
 * //=> Hello Sloth! What an interesting program!
 * ```
 *
 * @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 AsyncReducer.create}. Then each value in `asyncIterable` is added to
 * the accumulator and the current accumulator is updated using
 * {@link AsyncReducer.add}. Finally, the resulting accumulator is transformed
 * using {@link AsyncReducer.finish} if specified. Multiple accumulators may be
 * created, added to, and then combined if supported via
 * {@link AsyncReducer.combine} and the next value of `asyncIterable` is ready
 * before promises from {@link AsyncReducer.add} resolve.
 *
 * If `asyncReducer` is an async optional reducer (no
 * {@link AsyncReducer.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
 * console.log(
 *   await pipe(
 *     asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
 *     reduceAsync((a, b) => `${a} ${b}`),
 *     getAsync,
 *   ),
 * )
 * //=> Hello World! What an interesting program!
 *
 * console.log(
 *   await pipe(
 *     asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
 *     reduceAsync({ create: () => ``, add: (a, b) => `${a} ${b}` }),
 *   ),
 * )
 * //=> Hello World! What an interesting program!
 * ```
 *
 * @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`.
 *
 * Informally, an initial accumulator is created using
 * {@link AsyncReducer.create}. Then each value in `concurIterable` is added to
 * the accumulator and the current accumulator is updated using
 * {@link AsyncReducer.add}. Finally, the resulting accumulator is transformed
 * using {@link AsyncReducer.finish} if specified. Multiple accumulators may be
 * created, added to, and then combined if supported via
 * {@link AsyncReducer.combine} and the next value of `concurIterable` is ready
 * before promises from {@link AsyncReducer.add} resolve.
 *
 * If `asyncReducer` is an async optional reducer (no
 * {@link AsyncReducer.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
 * console.log(
 *   await pipe(
 *     asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
 *     reduceAsync((a, b) => `${a} ${b}`),
 *     getAsync,
 *   ),
 * )
 * //=> Hello World! What an interesting program!
 *
 * console.log(
 *   await pipe(
 *     asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
 *     reduceAsync({ create: () => ``, add: (a, b) => `${a} ${b}` }),
 *   ),
 * )
 * //=> Hello World! What an interesting program!
 * ```
 *
 * @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>
}

/**
 * Returns a {@link Reducer} that collects values to an `Array`.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `more sloth`]),
 *     take(4),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'more sloth', 'sloth', 'more 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
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `more sloth`]),
 *     take(4),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> Set(2) { 'sloth', 'more sloth' }
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `more sloth`]),
 *     take(4),
 *     map(string => ({ sloth: string })),
 *     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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     map(string => [string, string.length]),
 *     reduce(toObject()),
 *   ),
 * )
 * //=> { sloth: 5, 'more sloth': 10, 'even more sloth': 15 }
 * ```
 *
 * @category Collections
 * @since v0.0.1
 */
declare const toObject: <Key extends keyof never, 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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     map(string => [string, string.length]),
 *     reduce(toMap()),
 *   ),
 * )
 * //=> Map(3) { 'sloth' => 5, 'more sloth' => 10, 'even more sloth' => 15 }
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     map(string => [{ sloth: string }, string.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
 * console.log(
 *   pipe(
 *     [`sloth`, `some sloth`, `sleep`, `more sloth`, `even more sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toArray(), toMap())),
 *   ),
 * )
 * //=> Map(3) {
 * //=>   5 => [ 'sloth', 'sleep' ],
 * //=>   10 => [ 'some sloth', 'more sloth' ],
 * //=>   15 => [ 'even more sloth' ]
 * //=> }
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `some sloth`, `sleep`, `more sloth`, `even more sloth`],
 *     map(string => string.length),
 *     reduce(toMultiple([toSet(), toCount(), toJoin(`,`)])),
 *   ),
 * )
 * //=> [ Set(3) { 5, 10, 15 }, 5, '5,10,5,10,15' ]
 *
 * console.log(
 *   pipe(
 *     [`sloth`, `some sloth`, `sleep`, `more sloth`, `even more sloth`],
 *     map(string => string.length),
 *     reduce(
 *       toMultiple({
 *         set: toSet(),
 *         count: toCount(),
 *         string: toJoin(`,`),
 *       }),
 *     ),
 *   ),
 * )
 * //=> { set: Set(3) { 5, 10, 15 }, count: 5, string: '5,10,5,10,15' }
 * ```
 *
 * @category Collections
 * @since v2.0.0
 */
declare const toMultiple: {
  <
    Value,
    Reducers extends
      | readonly [RawReducerWithoutFinish<Value, any>]
      | readonly RawReducerWithoutFinish<Value, any>[]
      | Readonly<Record<keyof never, 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<
            keyof never,
            | 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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `sleep`, `some sloth`],
 *     map(string => [string.length, string]),
 *     reduce(toGrouped(toJoin(`,`), toMap())),
 *   ),
 * )
 * //=> Map(2) { 5 => 'sloth,sleep', 10 => 'more sloth,some sloth' }
 * ```
 *
 * @category Collections
 * @since v2.0.0
 */
declare const toJoin: (separator: string) => Reducer<unknown, unknown, string>

/**
 * Returns the result of concatenating the values of `iterable` to a string
 * where values are separated by `separator`.
 *
 * Like `Array.prototype.join`, but for iterables, but does not treat `null`,
 * `undefined`, or `[]` specially.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     join(`, `),
 *   ),
 * )
 * //=> sloth, more sloth, even more sloth
 * ```
 *
 * @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 result of concatenating the values of
 * `asyncIterable` to a string where values are separated by `separator`.
 *
 * Like `Array.prototype.join`, but for async iterables, but does not treat
 * `null`, `undefined`, or `[]` specially.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     joinAsync(`, `),
 *   ),
 * )
 * //=> sloth, more sloth, even more sloth
 * ```
 *
 * @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 result of concatenating the values of
 * `concurIterable` to a string where values are separated by `separator`.
 *
 * Like `Array.prototype.join`, but for concur iterables, but does not treat
 * `null`, `undefined`, or `[]` specially.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     joinConcur(`, `),
 *   ),
 * )
 * //=> sloth, more sloth, even more sloth
 * ```
 *
 * @category Collections
 * @since v0.0.2
 */
declare const joinConcur: {
  (
    separator: string,
  ): (concurIterable: ConcurIterable<unknown>) => Promise<string>
  (separator: string, concurIterable: ConcurIterable<unknown>): Promise<string>
}

/**
 * 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
 * console.log(
 *   pipe(
 *     [`sloth party`, `building`, `sloths in trees`, `city`],
 *     filter(string => string.includes(`sloth`)),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth party', 'sloths in trees' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth party`, `building`, `sloths in trees`, `city`]),
 *     filterAsync(string => string.includes(`sloth`)),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth party', 'sloths in trees' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth party`, `building`, `sloths in trees`, `city`]),
 *     filterConcur(string => string.includes(`sloth`)),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth party', 'sloths in trees' ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [
 *       { sloth: `sloth party` },
 *       { notSloth: `building` },
 *       { sloth: `sloths in trees` },
 *       { notSloth: `city` },
 *     ],
 *     filterMap(object => object.sloth),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth party', 'sloths in trees' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([
 *       { sloth: `sloth party` },
 *       { notSloth: `building` },
 *       { sloth: `sloths in trees` },
 *       { notSloth: `city` },
 *     ]),
 *     filterMapAsync(object => object.sloth),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth party', 'sloths in trees' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([
 *       { sloth: `sloth party` },
 *       { notSloth: `building` },
 *       { sloth: `sloths in trees` },
 *       { notSloth: `city` },
 *     ]),
 *     filterMapConcur(object => object.sloth),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth party', 'sloths in trees' ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `sleep`, `fast`, `slow`, `mean`],
 *     exclude([`mean`, `fast`]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'sleep', 'slow' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `sleep`, `fast`, `slow`, `mean`]),
 *     excludeAsync([`mean`, `fast`]),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'sleep', 'slow' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `sleep`, `fast`, `slow`, `mean`]),
 *     excludeConcur([`mean`, `fast`]),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'sleep', 'slow' ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `sleep`, `fast`, `slow`, `mean`],
 *     uniqueBy(word => word.length),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'fast' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `sleep`, `fast`, `slow`, `mean`]),
 *     uniqueByAsync(word => word.length),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'fast' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `sleep`, `fast`, `slow`, `mean`]),
 *     uniqueByConcur(word => word.length),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'fast' ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `not sloth`, `sloth`],
 *     unique,
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'not sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `not sloth`, `sloth`]),
 *     uniqueAsync,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'not sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `not sloth`, `sloth`]),
 *     uniqueConcur,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'not sloth' ]
 * ```
 *
 * @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
 * const iterable = [1, 2, `sloth`, 4, `other string`]
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     find(value => typeof value === `string`),
 *     or(() => `yawn!`),
 *   )
 * )
 * //=> sloth
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     find(value => Array.isArray(value)),
 *     or(() => `yawn!`),
 *   )
 * )
 * //=> yawn!
 * ```
 *
 * @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
 * const asyncIterable = asAsync([1, 2, `sloth`, 4, `other string`])
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     findAsync(value => typeof value === `string`),
 *     orAsync(() => `yawn!`),
 *   )
 * )
 * //=> sloth
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     findAsync(value => Array.isArray(value)),
 *     orAsync(() => `yawn!`),
 *   )
 * )
 * //=> yawn!
 * ```
 *
 * @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.
 *
 * Like `Array.prototype.find`, but for concur iterables.
 *
 * @example
 * ```js
 * const concurIterable = asConcur([1, 2, `sloth`, 4, `other string`])
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     findConcur(value => typeof value === `string`),
 *     orConcur(() => `yawn`),
 *   ),
 * )
 * //=> sloth
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     findConcur(value => Array.isArray(value)),
 *     orConcur(() => `yawn`),
 *   ),
 * )
 * //=> yawn!
 * ```
 *
 * @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
 * const iterable = [1, 2, `sloth`, 4, `other string`]
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     findLast(value => typeof value === `string`),
 *     or(() => `yawn!`),
 *   ),
 * )
 * //=> other string
 *
 * console.log(
 *   pipe(
 *     iterable,
 *     findLast(value => Array.isArray(value)),
 *     or(() => `yawn!`),
 *   ),
 * )
 * //=> yawn!
 * ```
 *
 * @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
 * const asyncIterable = asAsync([1, 2, `sloth`, 4, `other string`])
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     findLastAsync(value => typeof value === `string`),
 *     orAsync(() => `yawn!`),
 *   ),
 * )
 * //=> other string
 *
 * console.log(
 *   await pipe(
 *     asyncIterable,
 *     findLastAsync(value => Array.isArray(value)),
 *     orAsync(() => `yawn!`),
 *   ),
 * )
 * //=> yawn!
 * ```
 *
 * @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.
 *
 * @example
 * ```js
 * const concurIterable = asConcur([1, 2, `sloth`, 4, `other string`])
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     findLastConcur(value => typeof value === `string`),
 *     orConcur(() => `yawn!`),
 *   ),
 * )
 * //=> other string
 *
 * console.log(
 *   await pipe(
 *     concurIterable,
 *     findLastConcur(value => Array.isArray(value)),
 *     orConcur(() => `yawn!`),
 *   ),
 * )
 * //=> yawn!
 * ```
 *
 * @category Filters
 * @since v0.0.2
 */
declare const findLastConcur: FindConcur

/**
 * 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.
 *
 * @category Generators
 * @since v0.1.0
 */
declare const keys: {
  <Key>(object: ReadonlyMap<Key, unknown>): Iterable<Key>
  <Key extends keyof never>(
    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.
 *
 * @category Generators
 * @since v0.1.0
 */
declare const values: <Value>(
  object:
    | ReadonlyMap<unknown, Value>
    | ReadonlySet<Value>
    | Readonly<Record<keyof never, 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.
 *
 * @category Generators
 * @since v0.1.0
 */
declare const entries: {
  <Key, Value>(object: {
    entries: () => Iterable<[Key, Value]>
  }): Iterable<[Key, Value]>
  <Key extends keyof never, 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
 * console.log(
 *   pipe(
 *     generate(previousValue => previousValue + previousValue, `sloth`),
 *     take(3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'slothsloth', 'slothslothslothsloth' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     generateAsync(previousValue => previousValue + previousValue, `sloth`),
 *     takeAsync(3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 'slothsloth', 'slothslothslothsloth' ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     repeat(`sloth`),
 *     take(3),
 *     join(`, `),
 *   ),
 * )
 * //=> 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.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     cycle([`sloth`, `more sloth`]),
 *     take(6),
 *     join(`, `),
 *   ),
 * )
 * //=> sloth, more sloth, sloth, more sloth, sloth, more sloth
 * ```
 *
 * @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`.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     cycleAsync(asAsync([`sloth`, `more sloth`])),
 *     takeAsync(6),
 *     joinAsync(`, `),
 *   ),
 * )
 * //=> sloth, more sloth, sloth, more sloth, sloth, more sloth
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const cycleAsync: <Value>(
  asyncIterable: AsyncIterable<Value>,
) => AsyncIterable<Value>

/**
 * An iterable that yields integers in a range. Has a method for obtaining a new
 * iterable that skips numbers 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.
   */
  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
 * console.log([...rangeTo(0, 6)])
 * //=> [ 0, 1, 2, 3, 4, 5, 6 ]
 *
 * console.log([...rangeTo(0, 6).step(2)])
 * //=> [ 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
 * console.log([...rangeUntil(0, 6)])
 * //=> [ 0, 1, 2, 3, 4, 5 ]
 *
 * console.log([...rangeUntil(0, 6).step(2)])
 * //=> [ 0, 2, 4 ]
 * ```
 *
 * @category Generators
 * @since v0.0.1
 */
declare const rangeUntil: Range

/** @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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     all(string => string.length > 8),
 *   ),
 * )
 * //=> 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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     allAsync(string => string.length > 8),
 *   ),
 * )
 * //=> 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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     allConcur(string => string.length > 8),
 *   ),
 * )
 * //=> 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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     any(string => string.length > 8),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     anyAsync(string => string.length > 8),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     anyConcur(string => string.length > 8),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     none(string => string.length > 8),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     noneAsync(string => string.length > 8),
 *   ),
 * )
 * //=> false
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     noneConcur(string => string.length > 8),
 *   ),
 * )
 * //=> 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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     includes(3),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     includesAsync(3),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     includesConcur(3),
 *   ),
 * )
 * //=> true
 * ```
 *
 * @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>
}

/**
 * Returns an iterable equivalent to `iterable` that applies `fn` to each value
 * of `iterable` as it is iterated.
 *
 * @example
 * ```js
 * const sloths = [`carl`, `frank`, `phil`]
 *
 * console.log([...each(console.log, sloths)])
 * //=> carl
 * //=> frank
 * //=> phil
 * //=> [ 'carl', 'frank', 'phil' ]
 * ```
 *
 * @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
 * const eachedSloths = await pipe(
 *   asAsync([`carl`, `frank`, `phil`]),
 *   eachAsync(console.log),
 *   reduceAsync(toArray()),
 * )
 * //=> carl
 * //=> frank
 * //=> phil
 *
 * console.log(eachedSloths)
 * //=> [ 'carl', 'frank', 'phil' ]
 * ```
 *
 * @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
 * const eachedSloths = await pipe(
 *   asConcur([`carl`, `frank`, `phil`]),
 *   eachConcur(console.log),
 *   reduceConcur(toArray()),
 * )
 * //=> carl
 * //=> frank
 * //=> phil
 *
 * console.log(eachedSloths)
 * //=> [ 'carl', 'frank', 'phil' ]
 * ```
 *
 * @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
 * const sloths = [`carl`, `frank`, `phil`]
 *
 * forEach(console.log, sloths)
 * //=> carl
 * //=> frank
 * //=> phil
 * ```
 *
 * @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
 * const sloths = asAsync([`carl`, `frank`, `phil`])
 *
 * await forEachAsync(console.log, sloths)
 * //=> carl
 * //=> frank
 * //=> phil
 * ```
 *
 * @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.
 *
 * Like `Array.prototype.forEach`, but for concur iterables.
 *
 * @example
 * ```js
 * const sloths = asConcur([`carl`, `frank`, `phil`])
 *
 * await forEachConcur(console.log, sloths)
 * //=> carl
 * //=> frank
 * //=> phil
 * //
 * ```
 *
 * @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
 * const iterable = pipe(
 *   [`sloth`, 2, 3],
 *   each(console.log),
 * )
 * // No output
 *
 * consume(iterable)
 * //=> sloth
 * //=> 2
 * //=> 3
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const consume: (iterable: Iterable<unknown>) => void

/**
 * Iterates through `asyncIterable` causing lazy operations to run.
 *
 * @example
 * ```js
 * const asyncIterable = pipe(
 *   asAsync([`sloth`, 2, 3]),
 *   eachAsync(console.log),
 * )
 * // No output
 *
 * await consumeAsync(asyncIterable)
 * //=> sloth
 * //=> 2
 * //=> 3
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const consumeAsync: (
  asyncIterable: AsyncIterable<unknown>,
) => Promise<void>

/**
 * Iterates through the `concurIterable` causing lazy operations to run.
 *
 * @example
 * ```js
 * const concurIterable = pipe(
 *   asConcur([`sloth`, 2, 3]),
 *   eachConcur(console.log),
 * )
 * // No output
 *
 * await consumeConcur(asyncIterable)
 * //=> sloth
 * //=> 2
 * //=> 3
 * ```
 *
 * @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.
 *
 * @example
 * ```js
 * const iterable = [`sloth`, `more sloth`, `even more sloth`]
 * const iterableWithEffects = each(console.log, iterable)
 *
 * const cachedIterable = cache(iterableWithEffects)
 *
 * console.log([...cachedIterable])
 * //=> sloth
 * //=> more sloth
 * //=> even more sloth
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log([...cachedIterable])
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 * ```
 *
 * @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.
 *
 * @example
 * ```js
 * const asyncIterable = asAsync([`sloth`, `more sloth`, `even more sloth`])
 * const asyncIterableWithEffects = eachAsync(console.log, asyncIterable)
 *
 * const cachedAsyncIterable = cacheAsync(asyncIterableWithEffects)
 *
 * console.log(await pipe(cachedAsyncIterable, reduceAsync(toArray())))
 * //=> sloth
 * //=> more sloth
 * //=> even more sloth
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(await pipe(cachedAsyncIterable, reduceAsync(toArray())))
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 * ```
 *
 * @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.
 *
 * @example
 * ```js
 * const concurIterable = asConcur([`sloth`, `more sloth`, `even more sloth`])
 * const concurIterableWithEffects = eachConcur(console.log, concurIterable)
 *
 * const cachedConcurIterable = cacheConcur(concurIterableWithEffects)
 *
 * console.log(await pipe(cachedConcurIterable, reduceConcur(toArray())))
 * //=> sloth
 * //=> more sloth
 * //=> even more sloth
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 *
 * console.log(await pipe(cachedConcurIterable, reduceConcur(toArray())))
 * //=> [ 'sloth', 'more sloth', 'even more sloth' ]
 * ```
 *
 * @category Side effects
 * @since v2.0.0
 */
declare const cacheConcur: <Value>(
  concurIterable: ConcurIterable<Value>,
) => ConcurIterable<Value>

/**
 * 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
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, 6, 7, 8, `sloth`],
 *     dropWhile(value => value < 5),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 5, 6, 7, 8, 'sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, 6, 7, 8, `sloth`]),
 *     dropWhileAsync(value => value < 5),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 5, 6, 7, 8, 'sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, 6, 7, 8, `sloth`]),
 *     dropWhileConcur(value => value < 5),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 5, 6, 7, 8, 'sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, 6, 7, 8, `sloth`],
 *     takeWhile(value => value < 5),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 4 ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, 6, 7, 8, `sloth`]),
 *     takeWhileAsync(value => value < 5),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 4 ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, 6, 7, 8, `sloth`]),
 *     takeWhileConcur(value => value < 5),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 4 ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, `sloth`],
 *     drop(3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 4, 5, 'sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, `sloth`]),
 *     dropAsync(3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 4, 5, 'sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, `sloth`]),
 *     dropConcur(3),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 4, 5, 'sloth' ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [1, 2, 3, 4, 5, `sloth`],
 *     take(3),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3 ]
 * ```
 *
 * @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.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([1, 2, 3, 4, 5, `sloth`]),
 *     takeAsync(3),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3 ]
 * ```
 *
 * @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.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([1, 2, 3, 4, 5, `sloth`]),
 *     takeConcur(3),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3 ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     first,
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const first: <Value>(iterable: Iterable<Value>) => Iterable<Value>

/**
 * Returns an async iterable containing the first value of `asyncIterable`, or
 * an empty async iterable if `asyncIterable` is empty.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     firstAsync,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const firstAsync: <Value>(
  asyncIterable: AsyncIterable<Value>,
) => AsyncIterable<Value>

/**
 * Returns a concur iterable containing the first value of `concurIterable`, or
 * an empty concur iterable if `concurIterable` is empty.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     firstConcur,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth' ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const firstConcur: <Value>(
  concurIterable: ConcurIterable<Value>,
) => ConcurIterable<Value>

/**
 * Returns an iterable containing the last value of `iterable`, or an empty
 * iterable if `iterable` is empty.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     last,
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'even more sloth' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const last: <Value>(iterable: Iterable<Value>) => Iterable<Value>

/**
 * Returns an async iterable containing the last value of `asyncIterable`, or
 * an empty async iterable if `asyncIterable` is empty.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     lastAsync,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'even more sloth' ]
 * ```
 *
 * @category Splices
 * @since v0.0.1
 */
declare const lastAsync: <Value>(
  asyncIterable: AsyncIterable<Value>,
) => AsyncIterable<Value>

/**
 * Returns a concur iterable containing the last value of `concurIterable`, or
 * an empty concur iterable if `concurIterable` is empty.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     lastConcur,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'even more sloth' ]
 * ```
 *
 * @category Splices
 * @since v0.0.2
 */
declare const lastConcur: <Value>(
  concurIterable: ConcurIterable<Value>,
) => ConcurIterable<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>

/**
 * 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>): Iterable<Value>
  <Value>(fn: Compare<Value>): (iterable: Iterable<Value>) => Iterable<Value>
}

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

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

/** @internal */
type MinOrMaxByConcur = {
  <Value>(
    fn: AsyncCompare<Value>,
    concurIterable: ConcurIterable<Value>,
  ): ConcurIterable<Value>
  <Value>(
    fn: AsyncCompare<Value>,
  ): (concurIterable: ConcurIterable<Value>) => ConcurIterable<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>,
  ): Iterable<MinMax<Value>>
  <Value>(
    fn: Compare<Value>,
  ): (iterable: Iterable<Value>) => Iterable<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>,
  ): AsyncIterable<MinMax<Value>>
  <Value>(
    fn: AsyncCompare<Value>,
  ): (asyncIterable: AsyncIterable<Value>) => AsyncIterable<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>,
  ): ConcurIterable<MinMax<Value>>
  <Value>(
    fn: (left: Value, right: Value) => MaybePromiseLike<number>,
  ): (concurIterable: ConcurIterable<Value>) => ConcurIterable<MinMax<Value>>
}

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

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

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

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

/** @internal */
type MinOrMaxWithConcur = {
  <Value>(
    fn: (value: Value) => MaybePromiseLike<number>,
    concurIterable: ConcurIterable<Value>,
  ): ConcurIterable<Value>
  <Value>(
    fn: (value: Value) => MaybePromiseLike<number>,
  ): (concurIterable: ConcurIterable<Value>) => ConcurIterable<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>,
  ): Iterable<MinMax<Value>>
  <Value>(
    fn: (value: Value) => number,
  ): (iterable: Iterable<Value>) => Iterable<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>,
  ): AsyncIterable<MinMax<Value>>
  <Value>(
    fn: (value: Value) => MaybePromiseLike<number>,
  ): (asyncIterable: AsyncIterable<Value>) => AsyncIterable<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>,
  ): ConcurIterable<MinMax<Value>>
  <Value>(
    fn: (value: Value) => MaybePromiseLike<number>,
  ): (concurIterable: ConcurIterable<Value>) => ConcurIterable<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>) => Iterable<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>,
) => AsyncIterable<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>,
) => ConcurIterable<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>) => Iterable<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>,
) => AsyncIterable<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>,
) => ConcurIterable<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>) => Iterable<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>,
) => AsyncIterable<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>,
) => ConcurIterable<MinMax<number>>

/**
 * Returns an iterable containing the values of `iterable` transformed by `fn`
 * in iteration order.
 *
 * Like `Array.prototype.map`, but for iterables.
 *
 * @example
 * ```js
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     map(string => string.length),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 5, 10, 15 ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     mapAsync(string => string.length),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 5, 10, 15 ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     mapConcur(string => string.length),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 5, 10, 15 ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     flatMap(string => [string, string.length]),
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 5, 'more sloth', 10, 'even more sloth', 15 ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     flatMapAsync(string => [string, string.length]),
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 5, 'more sloth', 10, 'even more sloth', 15 ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     flatMapConcur(string => [string, string.length]),
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 'sloth', 5, 'more sloth', 10, 'even more sloth', 15 ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [[1, 2], [3, `sloth`, 5], [6, 7]],
 *     flatten,
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 'sloth', 5, 6, 7 ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([asAsync([1, 2]), [3, `sloth`, 5], asAsync([6, 7])]),
 *     flattenAsync,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 'sloth', 5, 6, 7 ]
 * ```
 *
 * @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 concat} and {@link concatAsync}, this function does not
 * necessarily iterate over each iterable in sequence.
 *
 * @example
 * ```js
 * console.log(
 *   await pipe(
 *     asConcur([asConcur([1, 2]), [3, `sloth`, 5], asAsync([6, 7])]),
 *     flattenConcur,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ 1, 2, 3, 'sloth', 5, 6, 7 ]
 * ```
 *
 * @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
 * console.log(
 *   pipe(
 *     [`sloth`, `more sloth`, `even more sloth`],
 *     index,
 *     reduce(toArray()),
 *   ),
 * )
 * //=> [ [ 0, 'sloth' ], [ 1, 'more sloth' ], [ 2, 'even more sloth' ] ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asAsync([`sloth`, `more sloth`, `even more sloth`]),
 *     indexAsync,
 *     reduceAsync(toArray()),
 *   ),
 * )
 * //=> [ [ 0, 'sloth' ], [ 1, 'more sloth' ], [ 2, 'even more sloth' ] ]
 * ```
 *
 * @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
 * console.log(
 *   await pipe(
 *     asConcur([`sloth`, `more sloth`, `even more sloth`]),
 *     indexConcur,
 *     reduceConcur(toArray()),
 *   ),
 * )
 * //=> [ [ 0, 'sloth' ], [ 1, 'more sloth' ], [ 2, 'even more sloth' ] ]
 * ```
 *
 * @category Transforms
 * @since v2.0.0
 */
declare const indexConcur: <Value>(
  concurIterable: ConcurIterable<Value>,
) => ConcurIterable<[number, Value]>

export { type AsyncCompare, type AsyncFunctionReducer, type AsyncKeyedReducer, type AsyncOptional, type AsyncOptionalReducer, type AsyncReducer, type Compare, type ConcurIterable, type ConcurIterableApply, type ConcurOptional, type FunctionReducer, type KeyedReducer, type MinMax, NO_ENTRY, type Optional, type OptionalReducer, type RangeIterable, type RawAsyncKeyedReducer, type RawAsyncOptionalReducerWithFinish, type RawAsyncOptionalReducerWithoutFinish, type RawAsyncReducerWithFinish, type RawAsyncReducerWithoutFinish, type RawKeyedReducer, type RawOptionalReducerWithFinish, type RawOptionalReducerWithoutFinish, type RawReducerWithFinish, type RawReducerWithoutFinish, type Reducer, type WindowOptions, all, allAsync, allConcur, any, anyAsync, anyConcur, asAsync, asConcur, at, atAsync, atConcur, cache, cacheAsync, cacheConcur, chunk, chunkAsync, chunkConcur, compose, concat, concatAsync, concatConcur, 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 };
