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 | 1x 1x 378x 1x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1438x 1x 1x 1438x 1438x 1438x 1060x 1060x 1060x 1060x 1060x 1060x 1060x 1060x 1060x 1060x 1x 378x 378x 378x 378x | import {
Array,
flow,
HashMap,
HashSet,
identity,
Option,
pipe,
Tuple,
} from 'effect'
import type {
ChildToParent,
EdgeList,
EdgeMap,
ParentToChildren,
TreeEdge,
} from './types.js'
/**
* Build a `EdgeMap` index from a non-empty list of tree edges.
* @category internal
* @function
*/
export const indexParents = <A>(edges: EdgeList<A>): EdgeMap<A> =>
pipe(edges, Array.reduce(emptyEdgeMap(), addEdgeMap<A>))
// Add a previously unknown node and its optional parent to an
// `EdgeMap` map.
const addEdgeMap = <A>(index: EdgeMap<A>, edge: TreeEdge<A>): EdgeMap<A> =>
pipe(
[edge, index] as EdgeAndMap<A>,
updateRoots,
updateChildToParent,
updateParentToChildren,
Tuple.getSecond,
)
type EdgeAndMap<A> = [TreeEdge<A>, EdgeMap<A>]
type EdgeAndMapEndo = <A>(edgeAndMap: EdgeAndMap<A>) => EdgeAndMap<A>
// Update the roots map of a `EdgeMap` index with a new edge.
const updateRoots: EdgeAndMapEndo = ([[child, parent], {roots, ...rest}]) => [
[child, parent],
{
...rest,
roots: pipe(
roots,
pipe(
parent,
Option.match({
onNone: () => HashSet.add,
onSome: () => HashSet.remove,
}),
)(child),
),
},
]
// Update the child to parent map of a `EdgeMap` index with a new edge.
const updateChildToParent: EdgeAndMapEndo = ([
[child, parent],
{toParent, ...rest},
]) => [
[child, parent],
{
...rest,
toParent: pipe(
toParent,
pipe(
parent,
Option.match({
onNone: () => identity<ChildToParent<typeof child>>,
onSome: parent => HashMap.set(child, parent),
}),
),
),
},
]
// Update the parent to children map of an `EdgeMap` index with a new edge.
const updateParentToChildren: EdgeAndMapEndo = ([
[child, parent],
{toChildren, ...rest},
]) => [
[child, parent],
{
...rest,
toChildren: pipe(
parent,
Option.match({
onNone: () => toChildren,
onSome: addParent(toChildren, child),
}),
),
},
]
const addParent =
<A>(
toChildren: ParentToChildren<A>,
child: A,
): ((a: A) => ParentToChildren<A>) =>
parent =>
pipe(
toChildren,
HashMap.modifyAt(
parent,
flow(
Option.match({onNone: () => [child], onSome: Array.append(child)}),
Option.some,
),
),
)
// Create a new `EdgeMap` index.
const emptyEdgeMap = () => ({
roots: HashSet.empty(),
toParent: HashMap.empty(),
toChildren: HashMap.empty(),
})
|