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

100% Statements 33/33
100% Branches 3/3
100% Functions 1/1
100% Lines 33/33

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 581x   1x   1x   1x           1x 5x 5x 5x 5x 5x 5x 5x   5x 5x 5x 5x 5x   5x 5x 5x 5x 5x 5x 5x 115x 115x 115x 115x 5x 5x 5x 5x 5x                              
import {addLawSets, Law, lawTests} from '#law'
import {Contravariant as CN} from '@effect/typeclass'
import {flow, identity, pipe} from 'effect'
import type {TypeLambda} from 'effect/HKT'
import {invariantLaws} from './Invariant.js'
import type {BuildParameterized} from './given.js'
import {unfoldGiven} from './given.js'
 
/**
 * Typeclass laws for `Contravariant` and its requirement: `Invariant`.
 * @category typeclass laws
 */
export const contravariantLaws: BuildParameterized<ContravariantTypeLambda> = (
  given,
  suffix?,
) => {
  const {F, equalsFa, fa, ba, cb, equalsFc} = unfoldGiven(given)
  return pipe(
    lawTests(
      `Contravariant${suffix ?? ''}`,
 
      Law(
        'identity',
        'contramap(id) = id',
        fa,
      )(fa => equalsFa(F.contramap(fa, identity), fa)),
 
      Law(
        'composition',
        'fa ▹ contramap(ba) ▹ contramap(cb) = fa ▹ contramap(ba ∘ cb)',
        fa,
        ba,
        cb,
      )((fa, ba, cb) =>
        equalsFc(
          pipe(fa, F.contramap(ba), F.contramap(cb)),
          pipe(fa, F.contramap(flow(cb, ba))),
        ),
      ),
    ),
    pipe(given, invariantLaws, addLawSets),
  )
}
 
/**
 * Type lambda for the `Contravariant` typeclass.
 * @category type lambda
 */
export interface ContravariantTypeLambda extends TypeLambda {
  readonly type: CN.Contravariant<this['Target'] & TypeLambda>
}
 
declare module './given.js' {
  interface ParameterizedLambdas {
    Contravariant: ContravariantTypeLambda
  }
}