/**
 * **This module is experimental.**
 *
 * Not to be confused with TypeScript's enums, this module refers to
 * enumeration, modelled similarly to PureScript's `BoundedEnum`.
 *
 * Most functions in this module are extremely expensive if called on instances
 * of very large types.
 *
 * @since 0.17.0
 */
import type { Bounded } from "fp-ts/Bounded";
import * as O from "fp-ts/Option";
import type { Ord } from "fp-ts/Ord";
type Option<A> = O.Option<A>;
import * as NEA from "fp-ts/NonEmptyArray";
type NonEmptyArray<A> = NEA.NonEmptyArray<A>;
import type { Eq } from "fp-ts/Eq";
import * as L from "./Lazy";
type Lazy<A> = L.Lazy<A>;
/**
 * Typeclass for finite enumerations.
 *
 * The retraction laws state that when operations succeed, `succ` and `pred`
 * reverse one-another:
 *   pred >=> succ >=> pred = pred
 *   succ >=> pred >=> succ = succ
 *
 * The non-skipping laws state that calls to `succ` and `pred` should not skip
 * any members of the given type. For example, an instance for a sum type of
 * ordered members `A`, `B`, and `C` should traverse the members like so:
 * `A <-> B <-> C`, skipping no member and following the order defined by the
 * `Ord` instance.
 *
 * `fromEnum` should always return an integer. `toEnum` should not accept
 * non-integer inputs. They should both be zero-based.
 *
 * @example
 * import * as Bool from 'fp-ts-std/Boolean'
 * import { universe } from 'fp-ts-std/Enum'
 *
 * assert.deepStrictEqual(universe(Bool.Enum), [false, true])
 *
 * @category 0 Types
 * @since 0.17.0
 */
export type Enum<A> = Bounded<A> & {
    succ: (x: A) => Option<A>;
    pred: (x: A) => Option<A>;
    toEnum: (index: number) => Option<A>;
    fromEnum: (x: A) => number;
    cardinality: Lazy<number>;
};
/**
 * Returns a contiguous sequence of elements between `start` and `end`
 * inclusive. Behaviour is unspecified if `end` is not greater than `start`.
 *
 * @example
 * import { fromTo } from 'fp-ts-std/Enum'
 * import { EnumInt } from 'fp-ts-std/Number'
 *
 * const range = fromTo(EnumInt)
 *
 * assert.deepStrictEqual(range(0)(3), [0, 1, 2, 3])
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const fromTo: <A>(E: Enum<A>) => (start: A) => (limit: A) => NonEmptyArray<A>;
/**
 * Returns a sequence of elements from `first` until `limit` with step size
 * determined by the difference between `first` and `second`. Behaviour is
 * unspecified if `end` is not greater than `start` or `step` is non-positive.
 *
 * @example
 * import { fromThenTo } from 'fp-ts-std/Enum'
 * import { EnumInt } from 'fp-ts-std/Number'
 *
 * const f = fromThenTo(EnumInt)
 *
 * assert.deepStrictEqual(f(0)(2)(6), [0, 2, 4, 6])
 * assert.deepStrictEqual(f(0)(3)(5), [0, 3])
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const fromThenTo: <A>(E: Enum<A>) => (first: A) => (second: A) => (limit: A) => NonEmptyArray<A>;
/**
 * Produces all successors of `start` exclusive.
 *
 * @example
 * import { upFromExcl } from 'fp-ts-std/Enum'
 * import { Enum as EnumBool } from 'fp-ts-std/Boolean'
 *
 * const f = upFromExcl(EnumBool)
 *
 * assert.deepStrictEqual(f(false), [true])
 * assert.deepStrictEqual(f(true), [])
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const upFromExcl: <A>(E: Enum<A>) => (start: A) => A[];
/**
 * Produces all successors of `start` inclusive.
 *
 * @example
 * import { upFromIncl } from 'fp-ts-std/Enum'
 * import { Enum as EnumBool } from 'fp-ts-std/Boolean'
 *
 * const f = upFromIncl(EnumBool)
 *
 * assert.deepStrictEqual(f(false), [false, true])
 * assert.deepStrictEqual(f(true), [true])
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const upFromIncl: <A>(E: Enum<A>) => (start: A) => NonEmptyArray<A>;
/**
 * Produces all predecessors of `start` exclusive.
 *
 * @example
 * import { downFromExcl } from 'fp-ts-std/Enum'
 * import { Enum as EnumBool } from 'fp-ts-std/Boolean'
 *
 * const f = downFromExcl(EnumBool)
 *
 * assert.deepStrictEqual(f(true), [false])
 * assert.deepStrictEqual(f(false), [])
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const downFromExcl: <A>(E: Enum<A>) => (end: A) => A[];
/**
 * Produces all predecessors of `start` inclusive.
 *
 * @example
 * import { downFromIncl } from 'fp-ts-std/Enum'
 * import { Enum as EnumBool } from 'fp-ts-std/Boolean'
 *
 * const f = downFromIncl(EnumBool)
 *
 * assert.deepStrictEqual(f(true), [true, false])
 * assert.deepStrictEqual(f(false), [false])
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const downFromIncl: <A>(E: Enum<A>) => (start: A) => NonEmptyArray<A>;
/**
 * Provides a default, inefficient implementation of `cardinality`.
 *
 * @example
 * import { defaultCardinality } from 'fp-ts-std/Enum'
 * import { Enum as EnumBool } from 'fp-ts-std/Boolean'
 *
 * assert.strictEqual(defaultCardinality(EnumBool), 2)
 *
 * @category 3 Functions
 * @since 0.17.0
 */
export declare const defaultCardinality: <A>(E: Omit<Enum<A>, "cardinality">) => number;
/**
 * Enumerates every value of an `Enum` in ascending order.
 *
 * @example
 * import { universe } from 'fp-ts-std/Enum'
 * import { Enum as EnumBool } from 'fp-ts-std/Boolean'
 *
 * assert.deepStrictEqual(universe(EnumBool), [false, true])
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const universe: <A>(E: Enum<A>) => NonEmptyArray<A>;
/**
 * Creates a fallible function that's the inverse of `f`. `f` is expected to
 * return distinct `B` values for any given `A`; behaviour when this is not the
 * case is unspecified.
 *
 * Inverse mapping can be thought of as akin to a partial isomorphism. If the
 * types are totally isomorphic, consider instead defining an isomorphism to do
 * away with the infallibility.
 *
 * @example
 * import { inverseMap } from 'fp-ts-std/Enum'
 * import { Enum as EnumBool } from 'fp-ts-std/Boolean'
 * import { Show as ShowBool } from 'fp-ts/boolean'
 * import * as Str from 'fp-ts/string'
 * import * as O from 'fp-ts/Option'
 *
 * const parseBool = inverseMap(EnumBool)(Str.Eq)(ShowBool.show)
 *
 * assert.deepStrictEqual(parseBool("true"), O.some(true))
 * assert.deepStrictEqual(parseBool("false"), O.some(false))
 * assert.deepStrictEqual(parseBool("foobar"), O.none)
 *
 * @category 2 Typeclass Methods
 * @since 0.17.0
 */
export declare const inverseMap: <A>(E: Enum<A>) => <B>(Eq: Eq<B>) => (f: (x: A) => B) => (x: B) => Option<A>;
/**
 * Produces an Enum instance that's potentially both unlawful and unsafe from a
 * list of values. Convenient for partially enumerating wide or deep types that
 * contain a few very large types such as strings.
 *
 * The instance will be unsafe if `xs` does not contain every member of `A`. If
 * this is the case, the only function that can throw is `fromEnum`.
 *
 * Behaviour in case of duplicate values is unspecified.
 *
 * @example
 * import { Enum, getUnsafeConstantEnum } from 'fp-ts-std/Enum'
 * import * as Bool from 'fp-ts/boolean'
 * import { Enum as EnumBool1 } from 'fp-ts-std/Boolean'
 *
 * // A safe instance equivalent to the real instance albeit with worse
 * // performance characteristics.
 * const EnumBool2: Enum<boolean> = getUnsafeConstantEnum(Bool.Ord)([false, true])
 *
 * assert.strictEqual(EnumBool2.fromEnum(true), 1)
 *
 * assert.strictEqual(EnumBool1.fromEnum(true), EnumBool2.fromEnum(true))
 * assert.strictEqual(EnumBool1.fromEnum(false), EnumBool2.fromEnum(false))
 *
 * @category 1 Typeclass Instances
 * @since 0.17.0
 */
export declare const getUnsafeConstantEnum: <A>(Ord: Ord<A>) => (xs: NonEmptyArray<A>) => Enum<A>;
export {};
//# sourceMappingURL=Enum.d.ts.map