All files / src/schemes/fold annotate.ts

100% Statements 26/26
100% Branches 8/8
100% Functions 3/3
100% Lines 26/26

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                                       1x 105x 105x             1x 1x 12x 17x 17x 17x   1x 1x 122x 275x 275x 275x 275x 275x 275x 275x 275x 275x 275x  
import * as TreeF from '#treeF'
import {Effect, flow, pipe, Tuple} from 'effect'
import {fixTree, getValue, tree} from '../../tree/index.js'
import {type Tree} from '../../tree/types.js'
import type {TreeEffectFolder, TreeFolder} from './types.js'
 
/**
 * Converts a fold `φ` into one that _annotates_ tree values: every tree node
 * will be annotated with the intermediate value of the fold at the node.
 *
 * For example, to convert the `descendantCount` fold, that folds a tree into a
 * _tree total descendant count_ to one that annotates each node with its
 * _node total descendant count_:
 *
 * ```ts
 * const annotated = pipe(
 *   tree(42, [leaf(43)]),
 *   self, treeCata(annotateFolder(folds.descendantCount))),
 * )
 * ```
 * @category fold
 * @function
 */
export const annotateFolder = <A, B>(
  φ: TreeFolder<A, B>,
): TreeFolder<A, Tree<[A, B]>> => flow(annotateNode(φ), fixTree)
 
/**
 * Like {@link annotateFolder} but for _effect folders_.
 * @category fold
 * @function
 */
export const annotateEffectFolder =
  <A, B, E = never, R = never>(φ: TreeEffectFolder<A, B, E, R>) =>
  (self: TreeF.TreeF<A, Tree<[A, B]>>): Effect.Effect<Tree<[A, B]>, E, R> =>
    pipe(self, annotateNode(φ), TreeF.destruct, ([[a, effect], forest]) =>
      Effect.map(effect, b => tree([a, b], forest)),
    )
 
const annotateNode =
  <A, B, C>(φ: (tf: TreeF.TreeF<A, B>) => C) =>
  (self: TreeF.TreeF<A, Tree<[A, B]>>): TreeF.TreeF<[A, C], Tree<[A, B]>> =>
    pipe(
      self,
      TreeF.mapValue(
        a =>
          [
            a,
            pipe(self, TreeF.map(flow(getValue, Tuple.getSecond)), φ),
          ] as const,
      ),
    )