All files / src/laws/typeclass/parameterized Covariant.ts

100% Statements 36/36
100% Branches 5/5
100% Functions 2/2
100% Lines 36/36

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 651x   1x 1x   1x 1x   1x             1x 35x 35x   35x 35x 35x 35x 35x 35x 35x   1x 70x   70x 70x   70x 70x 70x 70x 70x   70x 70x 70x 70x 70x 70x 70x 5104x 70x 70x 70x                              
import {addLawSets, Law, lawTests} from '#law'
import {Covariant as CO} from '@effect/typeclass'
import {Covariant as optionCovariant} from '@effect/typeclass/data/Option'
import {flow, identity, pipe} from 'effect'
import type {TypeLambda} from 'effect/HKT'
import {invariantLaws} from './Invariant.js'
import {withOuterOption} from './compose.js'
import type {BuildParameterized} from './given.js'
import {unfoldGiven} from './given.js'
import {BuildInternal} from './internal.js'
 
/**
 * Typeclass laws for `Covariant` and its requirement `Invariant`.
 * @category typeclass laws
 */
export const covariantLaws: BuildParameterized<CovariantTypeLambda> = (
  given,
  suffix?,
) =>
  pipe(
    buildLaws(`Covariant${suffix ?? ''}`, given),
    pipe(given, invariantLaws, addLawSets),
    addLawSets(
      buildLaws(...withOuterOption('Covariant', given, optionCovariant)),
    ),
  )
 
const buildLaws: BuildInternal<CovariantTypeLambda> = (name, given) => {
  const {F, ab, bc, equalsFa, equalsFc, fa} = unfoldGiven(given)
 
  return lawTests(
    name,
 
    Law(
      'identity',
      'map(id) = id',
      fa,
    )(fa => equalsFa(F.map(fa, identity), fa)),
 
    Law(
      'composition',
      'map(bc ∘ ab) = map(bc) ∘ map(ab)',
      fa,
      ab,
      bc,
    )((fa, ab, bc) =>
      equalsFc(F.map(fa, flow(ab, bc)), pipe(fa, F.map(ab), F.map(bc))),
    ),
  )
}
 
/**
 * Type lambda for the `Covariant` typeclass.
 * @category type lambda
 */
export interface CovariantTypeLambda extends TypeLambda {
  readonly type: CO.Covariant<this['Target'] & TypeLambda>
}
 
declare module './given.js' {
  interface ParameterizedLambdas {
    Covariant: CovariantTypeLambda
  }
}