effect-ts-laws
Version:
effect-ts law testing using fast-check.
27 lines • 1.96 kB
JavaScript
import { addLawSets, Law, lawTests } from '#law';
import { SemiApplicative as SE, } from '@effect/typeclass';
import { pipe } from 'effect';
import { unfoldGiven } from './given.js';
import { semiAlternativeLaws } from './SemiAlternative.js';
/**
* Typeclass laws for `Alternative`.
* @category typeclass laws
*/
export const alternativeLaws = (given, suffix) => pipe(buildLaws(`Alternative${suffix ?? ''}`, given), pipe(given, semiAlternativeLaws, addLawSets));
const buildLaws = (name, given) => {
const unfolded = unfoldGiven(given), { F, equalsFa, fa } = unfolded, { coproduct, coproductAll } = F, isApplicative = 'productAll' in F && 'of' in F;
return lawTests(name, Law('left identity', '∅ ⊕ fa = fa', fa)(fa => equalsFa(coproduct(fa, F.zero()), fa)), Law('right identity', 'fa ⊕ ∅ = fa', fa)(fa => equalsFa(coproduct(F.zero(), fa), fa)), Law('coproductAll zero', 'coproductAll([]) = ∅', fa)(() => equalsFa(coproductAll([]), F.zero())), ...(isApplicative ? buildApplicativeLaws(given) : []));
};
// Extra laws for alternatives that have an applicative instance.
const buildApplicativeLaws = (given) => {
const { F, equalsFb, fa, ab, fabOf } = unfoldGiven(given), { coproduct, map } = F;
const Ap = F, ap = SE.ap(Ap), of = Ap.of, fab = fabOf(of);
return [
Law('right absorption', 'ap(fab, ∅) = ∅', fab)(fab => equalsFb(ap(fab, F.zero()), F.zero())),
Law('left distributivity', 'coproduct(fa₁, fa₂) ▹ map(ab) =' +
' coproduct(map(fa₁, ab), map(fa₂, ab))', fa, fa, ab)((fa1, fa2, ab) => equalsFb(pipe(coproduct(fa1, fa2), map(ab)), coproduct(map(fa1, ab), map(fa2, ab)))),
Law('right distributivity', 'coproduct(fab₁, fab₂) ▹ ap(fa) =' +
' coproduct(ap(fab₁, fa), ap(fab₂, fa))', fa, fab, fab)((fa, fab1, fab2) => equalsFb(pipe(coproduct(fab1, fab2), ap(fa)), coproduct(ap(fab1, fa), ap(fab2, fa)))),
];
};
//# sourceMappingURL=Alternative.js.map