import type { ParameterOverrides, UnknownLaw } from './law.js';
/**
 * A `LawSet` is a recursive data structure with an array of {@link Law}s
 * and an array of base `LawSet`s that models the laws required
 * by some function or datatype. The `LawSet` passes only if all its
 * `LawSet`s and all its own laws pass.
 *
 * You can try to find counterexamples to a set of laws using the functions
 * {@link checkLaw} and {@link checkLaws}.
 *
 * Functions in the `ts-effect-laws/test` entry point will try to find
 * counterexamples as part of a [vitest](https://vitest.dev/) test.
 *
 * Laws will be deduplicated in the scope of a run of `checkLaw` and
 * `checkLaws`, so that the same law will not run more than once per
 * datatype.
 *
 * This is required because typeclass laws are arranged in a parallel `extends`
 * hierarchy to the typeclasses themselves, so that a law could appear multiple
 * times in a test.
 *
 * Consider for example the law tests for `Array`. It has instances we wish to
 * check both for `Applicative` and for `Monad`. In `effect-ts`, both extend
 * `Covariant`. Thus testing the `Array` instance for `Applicative` will run the
 * laws for `Covariant`. But testing for the `Monad` laws will run the
 * `Covariant` law tests _again_. Deduplication avoids this issue.
 *
 * A `LawSet` can be tested by calling `testLaws(lawSet)` inside a `vitest`
 * suite, and will appear in the test results as a list of tests grouped inside
 * a `describe()` block, if it has a name, or as a flat list of test blocks if
 * it does not. The function must be imported from `effect-ts-laws/vitest`.
 * @category model
 */
export interface LawSet {
    /**
     * Optional name of unit under test. Runner uses this for `describe()`
     * block name. If missing, no `describe()` block is wrapped around
     * child laws.
     */
    name?: string;
    /**
     * Possibly empty list of `LawSet`s that must pass before we run the laws
     * in this set.
     */
    sets: LawSet[];
    /**
     * Possibly empty list laws that must pass for the law set to pass.
     */
    laws: UnknownLaw[];
}
/**
 * Assemble a set of laws for some unit under test. You can check them using the
 * functions {@link checkLaw} and {@link checkLaws }. They can be tested in a
 * [vitest](https://vitest.dev/) test suite using the
 * [testLaw](https://middle-ages.github.io/effect-ts-laws-docs/functions/vitest.testLaw.html)
 * and
 * [testLaw](https://middle-ages.github.io/effect-ts-laws-docs/functions/vitest.testLaw.html)
 * functions.
 * @example
 * import {checkLaws, Law, LawSet, tinyPositive} from 'effect-ts-laws'
 *
 * // A pair of laws with no law sets.
 * const setA: LawSet = LawSet()(
 *   'some feature under test',
 *   Law('law₁', '∀n ∈ ℕ: n = n', tinyPositive)(x => x === x),
 *   Law('law₂', '∀n ∈ ℕ: n ≤ n', tinyPositive)(x => x <= x),
 * )
 *
 * // Another that will run “setA” _before_ its own laws
 * const setB: LawSet = LawSet(setA)(
 *   'another feature under test',
 *   Law('law₁', '∀n ∈ ℕ: n - n = 0', tinyPositive)(x => x - x === 0),
 * )
 *
 * // Will check “setA” as a prerequisite
 * assert.deepStrictEqual(checkLaws(setB), [])
 * @param sets - Requirements for the new `LawSet`.
 * @category constructors
 */
export declare const LawSet: (...sets: LawSet[]) => (
/**
 * Test suite name.
 */
name?: string, 
/**
 * List of {@link Law}s that must pass for this `LawSet` to pass.
 */
...laws: UnknownLaw[]) => LawSet;
/**
 * Just like {@link LawSet}, but with an empty list of `LawSet`s.
 * @category constructors
 */
export declare const lawTests: (name?: string, ...laws: UnknownLaw[]) => LawSet;
/**
 * Just like {@link lawTests}, but explicitly anonymous.
 *
 * Anonymous LawSets do not appear as a distinct group in test results. Instead
 * they appear right next to their siblings.
 * @param laws - Laws under test.
 * @category constructors
 */
export declare const anonymousLawTests: (...laws: UnknownLaw[]) => LawSet;
/**
 * Just like {@link LawSet}, but with an empty list of laws, no
 * name, and the `sets` list is _deduped_ to avoid running
 * the same `LawSet` twice.
 * @category constructors
 */
export declare const lawSetTests: (...sets: LawSet[]) => LawSet;
/**
 * Adds a list of laws to the law set.
 * @category combinators
 */
export declare const addLaws: (...add: UnknownLaw[]) => ({ laws, ...rest }: LawSet) => LawSet;
/**
 * Adds a required child LawSets to a parent LawSet.
 * @param them - Child LawSet that will be added.
 * @returns Parent LawSet with the child LawSet added.
 * @category combinators
 */
export declare const addLawSets: (...them: LawSet[]) => ((lawSet: LawSet) => LawSet);
/**
 * Test the law set in a pure function with no `vitest` imports involved.
 *
 * See also {@link vitest.testLaws | testLaws}.
 * @returns Possibly empty array of failure messages.
 * @category harness
 */
export declare const checkLaws: ({ sets, laws }: LawSet, parameters?: ParameterOverrides) => string[];
/**
 * Check a list of `LawSet`s.
 * @returns Possibly empty array of failure messages.
 * @category harness
 */
export declare const checkLawSets: (parameters?: ParameterOverrides) => (
/** The law sets to test. */
...sets: LawSet[]) => string[];
/**
 * Filter the laws that are direct children of a LawSet by matching a regular
 * expression on the law _name_, and return the new filtered LawSet. LawSets
 * that survive the filter remain untouched.
 *
 * Useful when you need to remove from a LawSet laws that are problematic
 * perhaps because they are slow or difficult to generate.
 * @example
 * import {equivalenceLaws, filterLaws, tinyInteger} from 'effect-ts-laws'
 * import {Number as NU, pipe} from 'effect'
 *
 * // Extract reflexivity law from equivalence laws.
 * const reflexivity = pipe(
 *   {a: tinyInteger, equalsA: NU.Equivalence, F: NU.Equivalence},
 *   equivalenceLaws<number>,
 *   filterLaws(/reflexivity/),
 * )
 *
 * assert.equal(reflexivity.laws.length, 1)
 * assert.equal(reflexivity.laws[0]?.name, 'reflexivity')
 * @param re - Regular expression will be matched vs. law name.
 * @returns Input LawSet, but includes only laws with names matching `re`.
 * @category combinators
 */
export declare const filterLaws: (re: RegExp) => ({ laws, ...rest }: LawSet) => LawSet;
/**
 * Just like `filterLaws` but recursive.
 * @param re - Regular expression will be matched vs. law name.
 * @returns Input LawSet, but includes only laws with names matching `re`, with
 * all required LawSets also filtered.
 * @category combinators
 */
export declare const filterLawsDeep: (re: RegExp) => ({ laws, sets, ...rest }: LawSet) => LawSet;
/**
 * The anonymous empty LawSet.
 * @category constructors
 */
export declare const emptyLawSet: LawSet;
//# sourceMappingURL=lawSet.d.ts.map