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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1208x 1x 1x 1x 2234x 2234x 2234x 2234x 2234x 2234x 400x 400x 400x 400x 1026x 1026x 1026x 400x 2234x 2234x 1x 1x 580x 1x 1x 669x 125x 125x 125x 125x 125x 53x 125x 125x 1x 1x 580x 4x 16x 16x 16x 16x 16x 16x 16x 16x 16x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import * as TreeF from '#treeF'
import {fanout} from '#Pair'
import {Foldable as FO, Monoid} from '@effect/typeclass'
import * as Boolean from '@effect/typeclass/data/Boolean'
import {Array, Effect, flow, Function, pipe} from 'effect'
import {type Predicate} from 'effect/Predicate'
import {treeCata, type TreeFold, type TreeFolder} from '../schemes/fold.js'
import {match} from '../tree/index.js'
import {type Tree, type TreeTypeLambda} from '../tree/types.js'
/**
* Reduce a tree to a value of type `B` by applying the given reducer repeatedly
* over each element and the previous result of the reducer.
* @typeParam A The tree type.
* @param self The tree being reduced.
* @param initial The initial value will appear as the _previous_ value in the
* first iteration of the reducer.
* @returns - Reduced value of the same type as the given `initial` value.
* @category instances
* @function
*/
export const reduce: FO.Foldable<TreeTypeLambda>['reduce'] = Function.dual(
3,
<B, A>(self: Tree<A>, initial: B, reducer: (b: B, a: A) => B): B =>
pipe(initial, reduceEffect(reducer, self), Effect.runSync),
)
const reduceEffect =
<A, B = A>(reducer: (previous: B, current: A) => B, self: Tree<A>) =>
(initial: B): Effect.Effect<B> =>
pipe(
self,
match({
onLeaf: value => Effect.succeed(reducer(initial, value)),
onBranch: (value, forest) =>
Array.reduce(
forest,
Effect.succeed(reducer(initial, value)),
(initial, tree) =>
Effect.suspend(() =>
pipe(initial, Effect.flatMap(reduceEffect(reducer, tree))),
),
),
}),
)
/**
* Foldable instance for {@link Tree}.
* @category instances
*/
export const Foldable: FO.Foldable<TreeTypeLambda> = {reduce}
/**
* Fold a `Tree<A>` into an `A` using a `Monoid<A>`.
* @category instances
* @function
*/
export const foldMap: <A>(M: Monoid.Monoid<A>) => TreeFold<A, A> = monoid =>
treeCata(monoidFold(monoid))
/**
* Fold a single level of a tree using a monoid of the node type.
* @category instances
* @function
*/
export const monoidFold =
<A>(M: Monoid.Monoid<A>): TreeFolder<A, A> =>
self =>
pipe(
self,
TreeF.match<A, A, A>({
onLeaf: value => M.combine(M.empty, value),
onBranch: (value, forest) =>
Array.reduce(forest, M.combine(M.empty, value), M.combine),
}),
)
/**
* Fold single level in a tree of type `A` using a predicate of `A` and
* a boolean monoid.
* @category fold
* @function
*/
export const predicateFold =
(M: Monoid.Monoid<boolean>) =>
<A>(predicate: Predicate<A>): TreeFolder<A, boolean> =>
(self: TreeF.TreeF<A, boolean>) =>
M.combine(
...pipe(
self,
fanout(
flow(TreeF.getValue, predicate),
flow(TreeF.getForest, Array.reduce(M.empty, M.combine)),
),
),
)
/**
* The type of function the builds a tree folder from a predicate.
* @category instances
*/
export type BooleanFolder = <A>(
predicate: Predicate<A>,
) => TreeFolder<A, boolean>
/**
* The type of function the builds a tree fold from a predicate.
* @category instances
*/
export type BooleanFold = <A>(predicate: Predicate<A>) => TreeFold<A, boolean>
/**
* @category instances
* @function
*/
export const everyFold: BooleanFolder = predicateFold(Boolean.MonoidEvery)
/**
* @category instances
* @function
*/
export const someFold: BooleanFolder = predicateFold(Boolean.MonoidSome)
/**
* @category instances
* @function
*/
export const xorFold: BooleanFolder = predicateFold(Boolean.MonoidXor)
/**
* @category instances
* @function
*/
export const eqvFold: BooleanFolder = predicateFold(Boolean.MonoidEqv)
/**
* True if every node in the given boolean tree is true.
* @category instances
* @function
*/
export const every: Predicate<Tree<boolean>> = foldMap(Boolean.MonoidEvery)
/**
* True if some nodes in the given boolean tree are true.
* @category instances
* @function
*/
export const some: Predicate<Tree<boolean>> = foldMap(Boolean.MonoidSome)
/**
* Fold with `xor` over a boolean tree.
* @category instances
* @function
*/
export const xor: Predicate<Tree<boolean>> = foldMap(Boolean.MonoidXor)
/**
* Threads the logical connective `eqv`, also known as
* _bidirectional implication_, through all the nodes of a boolean tree and
* returns the boolean result.
* @category instances
* @function
*/
export const eqv: Predicate<Tree<boolean>> = foldMap(Boolean.MonoidEqv)
/**
* True if the given predicate is true for every node in the given tree.
* @category instances
* @function
*/
export const everyOf: BooleanFold = flow(everyFold, treeCata)
/**
* True if the given predicate is true for _some_ node or nodes in the given
* tree.
* @category instances
* @function
*/
export const someOf: BooleanFold = flow(someFold, treeCata)
|