Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 200x 200x 200x 200x 2x 2x 2x 2x 2x 2x 2x 2x 200x 200x 200x 200x 2x 2x 2x | import {addLawSets, Law, lawTests} from '#law' import { Alternative as AL, Applicative as AP, SemiApplicative as SE, } from '@effect/typeclass' import {pipe} from 'effect' import type {TypeLambda} from 'effect/HKT' import {UnderlyingArbitrary} from '../../../arbitrary.js' import type {BuildParameterized, ParameterizedGiven as Given} from './given.js' import {unfoldGiven} from './given.js' import {BuildInternal} from './internal.js' import {semiAlternativeLaws} from './SemiAlternative.js' /** * Typeclass laws for `Alternative`. * @category typeclass laws */ export const alternativeLaws: BuildParameterized<AlternativeTypeLambda> = ( given, suffix?, ) => pipe( buildLaws(`Alternative${suffix ?? ''}`, given), pipe(given, semiAlternativeLaws, addLawSets), ) const buildLaws: BuildInternal<AlternativeTypeLambda> = (name, given) => { const unfolded = unfoldGiven(given), {F, equalsFa, fa} = unfolded, {coproduct, coproductAll} = F, isApplicative = 'productAll' in F && 'of' in F type A = UnderlyingArbitrary<(typeof unfolded)['a']> return lawTests( name, Law( 'left identity', '∅ ⊕ fa = fa', fa, )(fa => equalsFa(coproduct(fa, F.zero<A>()), fa)), Law( 'right identity', 'fa ⊕ ∅ = fa', fa, )(fa => equalsFa(coproduct(F.zero<A>(), fa), fa)), Law( 'coproductAll zero', 'coproductAll([]) = ∅', fa, )(() => equalsFa(coproductAll([]), F.zero<A>())), ...(isApplicative ? buildApplicativeLaws(given) : []), ) } // Extra laws for alternatives that have an applicative instance. const buildApplicativeLaws = < F extends TypeLambda, A, B = A, C = A, R = never, O = unknown, E = unknown, >( given: Given<AlternativeTypeLambda, F, A, B, C, R, O, E>, ) => { const {F, equalsFb, fa, ab, fabOf} = unfoldGiven(given), {coproduct, map} = F const Ap = F as unknown as AP.Applicative<F>, ap = SE.ap(Ap), of = Ap.of, fab = fabOf(of) return [ Law( 'right absorption', 'ap(fab, ∅) = ∅', fab, )(fab => equalsFb(ap(fab, F.zero<A>()), F.zero<B>())), 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)), ), ), ] } /** * Type lambda for the `Alternative` typeclass. * @category type lambda */ export interface AlternativeTypeLambda extends TypeLambda { readonly type: AL.Alternative<this['Target'] & TypeLambda> } declare module './given.js' { interface ParameterizedLambdas { Alternative: AlternativeTypeLambda } } |