All files / src/instances Equivalence.ts

100% Statements 33/33
100% Branches 9/9
100% Functions 2/2
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 531x 1x 1x                       1x 79x   79x 79x 79x 79x 79x 79x 79x 79x             1x 1x 7043x 6964x 6964x 6964x 6964x 6964x   6964x 6422x 615x 6349x 1396x 1396x 1396x 1396x 1396x 1396x 4953x 6964x  
import {Array, Effect, Equivalence, flow, pipe} from 'effect'
import {constFalse, constTrue, tupled} from 'effect/Function'
import {destruct} from '../tree/data.js'
import type {Tree} from '../tree/types.js'
 
/**
 * Creates an `Equivalence` for a {@link Tree}<A> type, given an Equivalence for the
 * underlying type `A`.
 *
 * The equivalence will scan every node of both trees to make sure that are the
 * same, but will short-circuit on a mismatch.
 * @category instances
 * @function
 */
export const getEquivalence = <A>(
  equalsA: Equivalence.Equivalence<A>,
): Equivalence.Equivalence<Tree<A>> =>
  flow(
    getEquivalenceEffect(equalsA),
    Effect.match({
      onFailure: constFalse,
      onSuccess: constTrue,
    }),
    Effect.runSync,
  )
 
/**
 * List {@link getEquivalence} but the result is left inside an effect.
 * @category instances
 * @function
 */
export const getEquivalenceEffect =
  <A>(equalsA: Equivalence.Equivalence<A>) =>
  (self: Tree<A>, that: Tree<A>): Effect.Effect<void, undefined> => {
    const equals = getEquivalenceEffect(equalsA)
    const [[selfValue, selfForest], [thatValue, thatForest]] = [
      destruct(self),
      destruct(that),
    ]
 
    return !equalsA(selfValue, thatValue) ||
      selfForest.length !== thatForest.length
      ? Effect.fail(void {})
      : Array.isNonEmptyReadonlyArray(selfForest)
        ? Effect.suspend(() =>
            pipe(
              Array.zip(selfForest, thatForest),
              Effect.forEach(tupled(equals)),
            ),
          )
        : Effect.succeed({})
  }