All files / src/laws/typeclass/concrete Equivalence.ts

100% Statements 27/27
100% Branches 4/4
100% Functions 1/1
100% Lines 27/27

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 461x 1x       1x           1x 22x 22x 22x     22x 22x 22x 22x 22x 22x 22x 22x 22x   22x 22x 22x 22x 22x 22x 22x 22x   22x 22x 22x              
import {Law, lawTests} from '#law'
import {implies, Equivalence as BooleanEquivalence} from 'effect/Boolean'
import type {EquivalenceTypeLambda} from 'effect/Equivalence'
import {UnderlyingArbitrary} from '#arbitrary'
import type {BuildConcrete} from './given.js'
import {symmetry} from '#algebra'
 
/**
 * Build laws for `Equivalence`.
 * @category typeclass laws
 */
export const equivalenceLaws: BuildConcrete<EquivalenceTypeLambda> = ({
  F,
  a,
}) => {
  type A = UnderlyingArbitrary<typeof a>
 
  return lawTests(
    'Equivalence',
    Law(
      'transitivity',
      'a=b ∧ b=c ⇒ a=c',
      a,
      a,
      a,
    )((a: A, b: A, c: A) => implies(F(a, b) && F(b, c), F(a, c))),
 
    symmetry<A, boolean>(
      {
        f: F,
        a,
        equals: BooleanEquivalence,
      },
      'a=b ⇔ b=a',
    ),
 
    Law('reflexivity', 'a=a', a)((a: A) => F(a, a)),
  )
}
 
declare module './given.js' {
  interface ConcreteLambdas {
    Equivalence: EquivalenceTypeLambda
  }
}