All files / src/laws algebra.ts

100% Statements 29/29
100% Branches 6/6
100% Functions 3/3
100% Lines 29/29

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 611x               1x 36x 36x 36x 36x 36x         36x 36x 36x           1x 4x 4x 4x 4x 4x 4x           4x 4x 4x           1x 22x 22x 22x 22x 22x         22x 22x   22x  
import {Law} from '#law'
import type {Equivalence} from 'effect/Equivalence'
import fc from 'fast-check'
 
/**
 * Test that a binary operation is associative.
 * @category algebraic laws
 */
export const associativity = <A>(
  {
    f,
    a,
    equals,
  }: {
    f: (a: A, b: A) => A
    a: fc.Arbitrary<A>
    equals: Equivalence<A>
  },
  note = '(a ⊕ b) ⊕ c = a ⊕ (b ⊕ c)',
  name = 'associativity',
) => Law(name, note, a, a, a)((a, b, c) => equals(f(f(a, b), c), f(a, f(b, c))))
 
/**
 * Test the composition of two operations cancels each other.
 * @category algebraic laws
 */
export const inverse = <A, B>(
  {
    f,
    g,
    a,
    equals,
  }: {
    f: (a: A) => B
    g: (b: B) => A
    a: fc.Arbitrary<A>
    equals: Equivalence<A>
  },
  note = 'g ⚬ f = id',
  name = 'inverse',
) => Law(name, note, a)(a => equals(g(f(a)), a))
 
/**
 * Test that a binary operation is symmetric.
 * @category algebraic laws
 */
export const symmetry = <A, B>(
  {
    f,
    a,
    equals,
  }: {
    f: (left: A, right: A) => B
    a: fc.Arbitrary<A>
    equals: Equivalence<B>
  },
  note = 'f(a, b) = f(b, a)',
  name = 'symmetry',
) =>
  Law(name, note, a, a)((left, right) => equals(f(left, right), f(right, left)))