All files / src/schemes/fold replace.ts

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

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 501x 1x 1x 1x                                       1x 1x 101x 214x             1x 1x 25x   25x 84x 84x 84x   1x 1x 298x 298x 298x 298x 298x  
import * as TreeF from '#treeF'
import {Effect, pipe} 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 _replaces_ tree values: every tree node
 * will be replaced 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 where each node value is the
 * _node total descendant count_:
 *
 * ```ts
 * const replaced = pipe(
 *   tree(42, [leaf(43)]),
 *   self, treeCata(replaceFolder(folds.descendantCount))),
 * )
 * ```
 * @category fold
 * @function
 */
export const replaceFolder =
  <A, B>(φ: TreeFolder<A, B>): TreeFolder<A, Tree<B>> =>
  self =>
    pipe(self, replaceNode(φ), fixTree)
 
/**
 * Like {@link replaceFolder} but for _effect folders_.
 * @category fold
 * @function
 */
export const replaceEffectFolder =
  <A, B, E = never, R = never>(
    φ: TreeEffectFolder<A, B, E, R>,
  ): TreeEffectFolder<A, Tree<B>, E, R> =>
  self =>
    pipe(self, replaceNode(φ), TreeF.destruct, ([value, forest]) =>
      Effect.map(value, tree.curried(forest)),
    )
 
const replaceNode =
  <A, B, C>(φ: (tf: TreeF.TreeF<A, B>) => C) =>
  (self: TreeF.TreeF<A, Tree<B>>): TreeF.TreeF<C, Tree<B>> =>
    pipe(
      self,
      TreeF.mapValue(() => pipe(self, TreeF.map(getValue), φ)),
    )