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

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

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 641x 1x 1x 1x   1x             1x                 2x 2x 2x 2x 2x 2x 1598x 2x 2x 800x 2x 2x   2x 2x 2x 2x   2x 2x 2x 2x 2x 2x 2x 2x                                  
import {LawSet} from '#law'
import {Bicovariant as BI, Covariant as CO} from '@effect/typeclass'
import {identity, pipe} from 'effect'
import {dual} from 'effect/Function'
import type {Kind, TypeLambda} from 'effect/HKT'
import {covariantLaws} from './Covariant.js'
import type {BuildParameterized, ParameterizedGiven as Given} from './given.js'
 
/**
 * Typeclass laws for `Bicovariant`.
 * @category typeclass laws
 */
export const bicovariantLaws: BuildParameterized<BicovariantTypeLambda> = <
  F1 extends TypeLambda,
  A,
  B = A,
  C = A,
  R = never,
  O = unknown,
  E = unknown,
>(
  given: Given<BicovariantTypeLambda, F1, A, B, C, R, O, E>,
  suffix?: string,
) => {
  const {F} = given
  const [mapFirst, mapSecond]: Pair<CO.Covariant<F1>['map']> = [
    dual(2, <A, B>(fa: Kind<F1, R, O, E, A>, ab: (a: A) => B) =>
      pipe(fa, F.bimap(identity, ab)),
    ),
    dual(2, <D, E>(fa: Kind<F1, R, O, D, A>, od: (a: D) => E) =>
      pipe(fa, F.bimap(od, identity)),
    ),
  ]
 
  const [first, second]: Pair<CO.Covariant<F1>> = [
    {map: mapFirst, imap: CO.imap<F1>(mapFirst)},
    {map: mapSecond, imap: CO.imap<F1>(mapSecond)},
  ]
 
  return pipe(
    `Bicovariant${suffix ?? ''}`,
    LawSet(
      covariantLaws({...given, F: first}, '₁'),
      covariantLaws({...given, F: second}, '₂'),
    ),
  )
}
 
/**
 * Type lambda for the `Bicovariant` typeclass.
 * @category type lambda
 */
export interface BicovariantTypeLambda extends TypeLambda {
  readonly type: BI.Bicovariant<this['Target'] & TypeLambda>
}
 
declare module './given.js' {
  interface ParameterizedLambdas {
    Bicovariant: BicovariantTypeLambda
  }
}
 
type Pair<A> = [A, A]