All files / src/schemes/unfold index.ts

100% Statements 26/26
100% Branches 6/6
100% Functions 5/5
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 831x 1x 1x 1x                             1x 1x 1x             1x 298x 298x               1x   1x             1x 4x 4x                     1x 13x   13x 13x 13x 13x                     1x 1x 4x   4x 21x  
import {applyPair, fanout} from '#Pair'
import * as TreeF from '#treeF'
import {Effect, flow, pipe} from 'effect'
import {ana, anaE} from 'effect-ts-folds'
import type {
  ParentEffectUnfolder,
  ParentUnfolder,
  TreeEffectUnfold,
  TreeEffectUnfolder,
  TreeUnfold,
  TreeUnfolder,
} from './types.js'
 
/**
 * Unfold a tree.
 * @category unfold
 * @function
 */
export const treeAna: <A, B>(ψ: TreeUnfolder<A, B>) => TreeUnfold<A, B> = ana(
  TreeF.Traversable,
)
 
/**
 * Unfold a tree into an effect.
 * @category unfold
 * @function
 */
export const treeAnaE = <A, B, E = unknown, R = unknown>(
  ψ: TreeEffectUnfolder<A, B, E, R>,
): TreeEffectUnfold<A, B, E, R> => anaE(TreeF.Traversable)(ψ)
 
/**
 * The simplest unfold: unfold a tree as long as the given function of type
 * `(parent: A) ⇒ A[]` keeps producing new child nodes.
 * @category unfold
 * @function
 */
export const unfold: <A>(
  unfolder: ParentUnfolder<A>,
) => TreeUnfold<A, A> = unfolder => pipe(unfolder, byParentUnfold, treeAna)
 
/**
 * A version of {@link unfold} that unfolds into an effect.
 * @category unfold
 * @function
 */
export const unfoldEffect = <A, E = unknown, R = unknown>(
  unfolder: ParentEffectUnfolder<A, E, R>,
) => pipe(unfolder, byParentUnfoldEffect, treeAnaE)
 
/**
 * Unfold a level of a tree defined by its unfolding function which must decide,
 * given the current node, who are its children? Converts a value of type
 * {@link ParentUnfolder | ParentUnfolder<A>} into a value of type
 * {@link TreeUnfolder | TreeUnfolder<A, A>}.
 *
 * @category unfold
 * @function
 */
export const byParentUnfold = <A>(
  unfolder: ParentUnfolder<A>,
): TreeUnfolder<A, A> =>
  flow(
    fanout(unfolder, TreeF.treeF.flipped<A>),
    applyPair<A[], TreeF.TreeF<A, A>>,
  )
 
/**
 * A version of {@link byParentUnfold} that unfolds into an effect.
 * Converts a value of type
 * {@link ParentEffectUnfolder | ParentEffectUnfolder<A, E, R>}
 * into a value of type
 * {@link TreeEffectUnfolder | TreeEffectUnfolder<A, A, E, R>}.
 * @category unfold
 * @function
 */
export const byParentUnfoldEffect =
  <A, E = unknown, R = unknown>(
    unfolder: ParentEffectUnfolder<A, E, R>,
  ): TreeEffectUnfolder<A, A, E, R> =>
  a =>
    pipe(a, unfolder, Effect.map(TreeF.treeF.flipped(a)))