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

100% Statements 7/7
100% Branches 2/2
100% Functions 3/3
100% Lines 7/7

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                        45x                       2x 2x   1633x     800x       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]