@nlozgachev/pipelined 0.65.0 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/data.mjs CHANGED
@@ -1,50 +1,93 @@
1
- import { S as Deferred, _ as Maybe, i as isNonEmptyArr, s as Result } from "./Core-BHN87zoB.mjs";
1
+ import { S as Deferred, g as Maybe, i as isNonEmptyArr, n as Task, o as Result, r as Validation } from "./Core-BCN6WRzp.mjs";
2
2
  //#region src/Data/Arr.ts
3
3
  let ArrMaybe;
4
4
  (function(_ArrMaybe) {
5
- const traverse = _ArrMaybe.traverse = (f) => (data) => {
6
- const n = data.length;
5
+ const traverse = _ArrMaybe.traverse = (transform) => (items) => {
6
+ const n = items.length;
7
7
  const result = new Array(n);
8
8
  for (let i = 0; i < n; i++) {
9
- const mapped = f(data[i]);
9
+ const mapped = transform(items[i]);
10
10
  if (mapped.kind === "None") return Maybe.make.none();
11
11
  result[i] = mapped.value;
12
12
  }
13
13
  return Maybe.make.some(result);
14
14
  };
15
- _ArrMaybe.sequence = (data) => traverse((a) => a)(data);
15
+ _ArrMaybe.sequence = (items) => traverse((item) => item)(items);
16
16
  })(ArrMaybe || (ArrMaybe = {}));
17
17
  let ArrResult;
18
18
  (function(_ArrResult) {
19
- const traverse = _ArrResult.traverse = (f) => (data) => {
20
- const n = data.length;
19
+ const traverse = _ArrResult.traverse = (transform) => (items) => {
20
+ const n = items.length;
21
21
  const result = new Array(n);
22
22
  for (let i = 0; i < n; i++) {
23
- const mapped = f(data[i]);
23
+ const mapped = transform(items[i]);
24
24
  if (mapped.kind === "Err") return mapped;
25
25
  result[i] = mapped.value;
26
26
  }
27
27
  return Result.make.ok(result);
28
28
  };
29
- _ArrResult.sequence = (data) => traverse((a) => a)(data);
29
+ _ArrResult.sequence = (items) => traverse((item) => item)(items);
30
30
  })(ArrResult || (ArrResult = {}));
31
+ let ArrValidation;
32
+ (function(_ArrValidation) {
33
+ const traverse = _ArrValidation.traverse = (transform) => (items) => {
34
+ const n = items.length;
35
+ const result = new Array(n);
36
+ const errors = [];
37
+ for (let i = 0; i < n; i++) {
38
+ const mapped = transform(items[i]);
39
+ if (Validation.is.failed(mapped)) errors.push(...mapped.errors);
40
+ else if (errors.length === 0) result[i] = mapped.value;
41
+ }
42
+ return isNonEmptyArr(errors) ? Validation.make.failedAll(errors) : Validation.make.passed(result);
43
+ };
44
+ _ArrValidation.sequence = (items) => traverse((item) => item)(items);
45
+ })(ArrValidation || (ArrValidation = {}));
31
46
  let ArrTaskResult;
32
47
  (function(_ArrTaskResult) {
33
- const traverse = _ArrTaskResult.traverse = (f) => (data) => () => Deferred.from.Promise((async () => {
34
- const result = [];
35
- for (const a of data) {
36
- const r = await Deferred.to.Promise(f(a)());
37
- if (Result.is.err(r)) return r;
38
- result.push(r.value);
48
+ const traverse = _ArrTaskResult.traverse = (transform, options) => (items) => (signal) => Deferred.from.Promise((async () => {
49
+ const concurrency = options?.concurrency;
50
+ const len = items.length;
51
+ if (concurrency === void 0 || concurrency <= 1 || len <= 1) {
52
+ const result = [];
53
+ for (const a of items) {
54
+ const r = await Deferred.to.Promise(transform(a)(signal));
55
+ if (Result.is.err(r)) return r;
56
+ result.push(r.value);
57
+ }
58
+ return Result.make.ok(result);
39
59
  }
40
- return Result.make.ok(result);
60
+ return new Promise((resolve) => {
61
+ const results = new Array(len);
62
+ let nextIndex = 0;
63
+ let settled = false;
64
+ const worker = async () => {
65
+ while (nextIndex < len && !settled) {
66
+ const currentIndex = nextIndex++;
67
+ const r = await Deferred.to.Promise(transform(items[currentIndex])(signal));
68
+ if (settled) return;
69
+ if (Result.is.err(r)) {
70
+ settled = true;
71
+ resolve(r);
72
+ return;
73
+ }
74
+ results[currentIndex] = r.value;
75
+ }
76
+ };
77
+ const workerCount = Math.min(concurrency, len);
78
+ const workers = [];
79
+ for (let i = 0; i < workerCount; i++) workers.push(worker());
80
+ Promise.all(workers).then(() => {
81
+ if (!settled) resolve(Result.make.ok(results));
82
+ });
83
+ });
41
84
  })());
42
- _ArrTaskResult.sequence = (data) => traverse((a) => a)(data);
85
+ _ArrTaskResult.sequence = (items) => traverse((item) => item)(items);
43
86
  })(ArrTaskResult || (ArrTaskResult = {}));
44
87
  let ArrTask;
45
88
  (function(_ArrTask) {
46
- const traverse = _ArrTask.traverse = (f) => (data) => () => Deferred.from.Promise(Promise.all(data.map((a) => Deferred.to.Promise(f(a)()))));
47
- _ArrTask.sequence = (data) => traverse((a) => a)(data);
89
+ const traverse = _ArrTask.traverse = (transform, options) => (items) => Task.all(items.map(transform), options);
90
+ _ArrTask.sequence = (items) => traverse((item) => item)(items);
48
91
  _ArrTask.Result = ArrTaskResult;
49
92
  })(ArrTask || (ArrTask = {}));
50
93
  /**
@@ -74,96 +117,118 @@ let ArrTask;
74
117
  /**
75
118
  * Returns the first element of an array, or None if the array is empty.
76
119
  *
120
+ * @see {@link last} for accessing the final element.
121
+ * @see {@link tail} for all elements except the first.
122
+ *
77
123
  * @example
78
124
  * ```ts
79
125
  * Arr.head([1, 2, 3]); // Some(1)
80
126
  * Arr.head([]); // None
81
127
  * ```
82
128
  */
83
- const head = (data) => data.length > 0 ? Maybe.make.some(data[0]) : Maybe.make.none();
129
+ const head = (items) => items.length > 0 ? Maybe.make.some(items[0]) : Maybe.make.none();
84
130
  /**
85
131
  * Returns the last element of an array, or None if the array is empty.
86
132
  *
133
+ * @see {@link head} for accessing the first element.
134
+ * @see {@link init} for all elements except the last.
135
+ *
87
136
  * @example
88
137
  * ```ts
89
138
  * Arr.last([1, 2, 3]); // Some(3)
90
139
  * Arr.last([]); // None
91
140
  * ```
92
141
  */
93
- const last = (data) => data.length > 0 ? Maybe.make.some(data[data.length - 1]) : Maybe.make.none();
142
+ const last = (items) => items.length > 0 ? Maybe.make.some(items[items.length - 1]) : Maybe.make.none();
94
143
  /**
95
144
  * Returns all elements except the first, or None if the array is empty.
96
145
  *
146
+ * @see {@link head} for accessing the first element.
147
+ *
97
148
  * @example
98
149
  * ```ts
99
150
  * Arr.tail([1, 2, 3]); // Some([2, 3])
100
151
  * Arr.tail([]); // None
101
152
  * ```
102
153
  */
103
- const tail = (data) => data.length > 0 ? Maybe.make.some(data.slice(1)) : Maybe.make.none();
154
+ const tail = (items) => items.length > 0 ? Maybe.make.some(items.slice(1)) : Maybe.make.none();
104
155
  /**
105
156
  * Returns all elements except the last, or None if the array is empty.
106
157
  *
158
+ * @see {@link last} for accessing the final element.
159
+ *
107
160
  * @example
108
161
  * ```ts
109
162
  * Arr.init([1, 2, 3]); // Some([1, 2])
110
163
  * Arr.init([]); // None
111
164
  * ```
112
165
  */
113
- const init = (data) => data.length > 0 ? Maybe.make.some(data.slice(0, -1)) : Maybe.make.none();
166
+ const init = (items) => items.length > 0 ? Maybe.make.some(items.slice(0, -1)) : Maybe.make.none();
114
167
  /**
115
168
  * Returns the first element matching the predicate, or None.
116
169
  *
170
+ * @see {@link findLast} for finding the last matching element.
171
+ * @see {@link findIndex} for obtaining the index of the first matching element.
172
+ *
117
173
  * @example
118
174
  * ```ts
119
175
  * pipe([1, 2, 3, 4], Arr.findFirst(n => n > 2)); // Some(3)
120
176
  * ```
121
177
  */
122
- const findFirst = (predicate) => (data) => {
123
- const idx = data.findIndex(predicate);
124
- return idx !== -1 ? Maybe.make.some(data[idx]) : Maybe.make.none();
178
+ const findFirst = (predicate) => (items) => {
179
+ const idx = items.findIndex(predicate);
180
+ return idx !== -1 ? Maybe.make.some(items[idx]) : Maybe.make.none();
125
181
  };
126
182
  /**
127
183
  * Returns the last element matching the predicate, or None.
128
184
  *
185
+ * @see {@link findFirst} for finding the first matching element.
186
+ *
129
187
  * @example
130
188
  * ```ts
131
189
  * pipe([1, 2, 3, 4], Arr.findLast(n => n > 2)); // Some(4)
132
190
  * ```
133
191
  */
134
- const findLast = (predicate) => (data) => {
135
- for (let i = data.length - 1; i >= 0; i--) if (predicate(data[i])) return Maybe.make.some(data[i]);
192
+ const findLast = (predicate) => (items) => {
193
+ for (let i = items.length - 1; i >= 0; i--) if (predicate(items[i])) return Maybe.make.some(items[i]);
136
194
  return Maybe.make.none();
137
195
  };
138
196
  /**
139
197
  * Returns the index of the first element matching the predicate, or None.
140
198
  *
199
+ * @see {@link findFirst} for finding the matching element value.
200
+ *
141
201
  * @example
142
202
  * ```ts
143
203
  * pipe([1, 2, 3, 4], Arr.findIndex(n => n > 2)); // Some(2)
144
204
  * ```
145
205
  */
146
- const findIndex = (predicate) => (data) => {
147
- const idx = data.findIndex(predicate);
206
+ const findIndex = (predicate) => (items) => {
207
+ const idx = items.findIndex(predicate);
148
208
  return idx !== -1 ? Maybe.make.some(idx) : Maybe.make.none();
149
209
  };
150
210
  /**
151
211
  * Transforms each element of an array.
152
212
  *
213
+ * @see {@link flatMap} for mapping and flattening arrays.
214
+ * @see {@link mapWithIndex} for mapping with element indices.
215
+ *
153
216
  * @example
154
217
  * ```ts
155
218
  * pipe([1, 2, 3], Arr.map(n => n * 2)); // [2, 4, 6]
156
219
  * ```
157
220
  */
158
- const map$3 = (f) => (data) => {
159
- const n = data.length;
221
+ const map$3 = (transform) => (items) => {
222
+ const n = items.length;
160
223
  const result = new Array(n);
161
- for (let i = 0; i < n; i++) result[i] = f(data[i]);
224
+ for (let i = 0; i < n; i++) result[i] = transform(items[i]);
162
225
  return result;
163
226
  };
164
227
  /**
165
228
  * Transforms each element using both its value and its zero-based index.
166
229
  *
230
+ * @see {@link map} for mapping without indices.
231
+ *
167
232
  * @example
168
233
  * ```ts
169
234
  * pipe(
@@ -172,30 +237,34 @@ const map$3 = (f) => (data) => {
172
237
  * ); // [{ position: 1, value: "a" }, { position: 2, value: "b" }, { position: 3, value: "c" }]
173
238
  * ```
174
239
  */
175
- const mapWithIndex = (f) => (data) => {
176
- const n = data.length;
240
+ const mapWithIndex = (transform) => (items) => {
241
+ const n = items.length;
177
242
  const result = new Array(n);
178
- for (let i = 0; i < n; i++) result[i] = f(i, data[i]);
243
+ for (let i = 0; i < n; i++) result[i] = transform(i, items[i]);
179
244
  return result;
180
245
  };
181
246
  /**
182
247
  * Filters elements that satisfy the predicate.
183
248
  *
249
+ * @see {@link filterMap} for filtering and mapping simultaneously.
250
+ *
184
251
  * @example
185
252
  * ```ts
186
253
  * pipe([1, 2, 3, 4], Arr.filter(n => n % 2 === 0)); // [2, 4]
187
254
  * ```
188
255
  */
189
- const filter$3 = (predicate) => (data) => {
190
- const n = data.length;
256
+ const filter$3 = (predicate) => (items) => {
257
+ const n = items.length;
191
258
  const result = [];
192
- for (let i = 0; i < n; i++) if (predicate(data[i])) result.push(data[i]);
259
+ for (let i = 0; i < n; i++) if (predicate(items[i])) result.push(items[i]);
193
260
  return result;
194
261
  };
195
262
  /**
196
263
  * Maps each element to a Maybe and collects only the Some values.
197
264
  * Combines map and filter in a single pass.
198
265
  *
266
+ * @see {@link filter} for filtering with a boolean predicate.
267
+ *
199
268
  * @example
200
269
  * ```ts
201
270
  * const parseNum = (s: string): Maybe<number> => {
@@ -206,10 +275,10 @@ const filter$3 = (predicate) => (data) => {
206
275
  * pipe(["1", "abc", "3"], Arr.filterMap(parseNum)); // [1, 3]
207
276
  * ```
208
277
  */
209
- const filterMap$3 = (f) => (data) => {
278
+ const filterMap$3 = (transform) => (items) => {
210
279
  const result = [];
211
- for (let i = 0; i < data.length; i++) {
212
- const mapped = f(data[i]);
280
+ for (let i = 0; i < items.length; i++) {
281
+ const mapped = transform(items[i]);
213
282
  if (mapped.kind === "Some") result.push(mapped.value);
214
283
  }
215
284
  return result;
@@ -219,50 +288,59 @@ const filterMap$3 = (f) => (data) => {
219
288
  * First group contains elements that satisfy the predicate,
220
289
  * second group contains the rest.
221
290
  *
291
+ * @see {@link partitionMap} for partitioning with a Result function.
292
+ *
222
293
  * @example
223
294
  * ```ts
224
295
  * pipe([1, 2, 3, 4], Arr.partition(n => n % 2 === 0)); // [[2, 4], [1, 3]]
225
296
  * ```
226
297
  */
227
- const partition = (predicate) => (data) => {
298
+ const partition = (predicate) => (items) => {
228
299
  const pass = [];
229
300
  const fail = [];
230
- for (const a of data) (predicate(a) ? pass : fail).push(a);
301
+ for (const item of items) (predicate(item) ? pass : fail).push(item);
231
302
  return [pass, fail];
232
303
  };
233
304
  /**
234
305
  * Narrows a list of Maybe values down to a list of their underlying values,
235
306
  * discarding all None instances.
236
307
  *
308
+ * @see {@link separate} for dividing Results into error and success arrays.
309
+ *
237
310
  * @example
238
311
  * ```ts
239
312
  * Arr.compact([Maybe.make.some(1), Maybe.make.none(), Maybe.make.some(3)]); // [1, 3]
240
313
  * ```
241
314
  */
242
- const compact$2 = (data) => {
315
+ const compact$2 = (items) => {
243
316
  const result = [];
244
- for (const item of data) if (item.kind === "Some") result.push(item.value);
317
+ for (const item of items) if (item.kind === "Some") result.push(item.value);
245
318
  return result;
246
319
  };
247
320
  /**
248
321
  * Separates an array of Result values into two separate lists of errors and successes.
249
322
  * Returns a tuple containing `[errors, successes]`.
250
323
  *
324
+ * @see {@link compact} for extracting Some values from Maybe instances.
325
+ *
251
326
  * @example
252
327
  * ```ts
253
328
  * Arr.separate([Result.make.ok(1), Result.make.err("bad"), Result.make.ok(3)]); // [["bad"], [1, 3]]
254
329
  * ```
255
330
  */
256
- const separate = (data) => {
331
+ const separate = (items) => {
257
332
  const errors = [];
258
333
  const successes = [];
259
- for (const item of data) if (item.kind === "Ok") successes.push(item.value);
334
+ for (const item of items) if (item.kind === "Ok") successes.push(item.value);
260
335
  else errors.push(item.error);
261
336
  return [errors, successes];
262
337
  };
263
338
  /**
264
339
  * Maps each element to a Result, and separates the results into a tuple of failures and successes.
265
340
  *
341
+ * @see {@link partition} for partitioning with a boolean predicate.
342
+ * @see {@link partitionMaybe} for partitioning with a Maybe function.
343
+ *
266
344
  * @example
267
345
  * ```ts
268
346
  * pipe(
@@ -271,11 +349,11 @@ const separate = (data) => {
271
349
  * ); // [["odd: 1", "odd: 3"], [2, 4]]
272
350
  * ```
273
351
  */
274
- const partitionMap = (f) => (data) => {
352
+ const partitionMap = (transform) => (items) => {
275
353
  const errors = [];
276
354
  const successes = [];
277
- for (const item of data) {
278
- const mapped = f(item);
355
+ for (const item of items) {
356
+ const mapped = transform(item);
279
357
  if (mapped.kind === "Ok") successes.push(mapped.value);
280
358
  else errors.push(mapped.error);
281
359
  }
@@ -284,6 +362,8 @@ const partitionMap = (f) => (data) => {
284
362
  /**
285
363
  * Groups elements by a key function.
286
364
  *
365
+ * @see {@link indexBy} for indexing elements into a Map.
366
+ *
287
367
  * @example
288
368
  * ```ts
289
369
  * pipe(
@@ -292,27 +372,33 @@ const partitionMap = (f) => (data) => {
292
372
  * ); // { a: ["apple", "avocado"], b: ["banana"] }
293
373
  * ```
294
374
  */
295
- const groupBy$2 = (f) => (data) => {
375
+ const groupBy$2 = (keySelector) => (items) => {
296
376
  const result = {};
297
- for (const a of data) {
298
- const key = f(a);
377
+ for (const item of items) {
378
+ const key = keySelector(item);
299
379
  if (!result[key]) result[key] = [];
300
- result[key].push(a);
380
+ result[key].push(item);
301
381
  }
302
382
  return result;
303
383
  };
304
384
  /**
305
385
  * Removes duplicate elements using strict equality.
306
386
  *
387
+ * @see {@link uniqBy} for deduplicating by a key projection.
388
+ * @see {@link uniqWith} for deduplicating with custom equality.
389
+ *
307
390
  * @example
308
391
  * ```ts
309
392
  * Arr.uniq([1, 2, 2, 3, 1]); // [1, 2, 3]
310
393
  * ```
311
394
  */
312
- const uniq = (data) => data.length <= 1 ? data : [...new Set(data)];
395
+ const uniq = (items) => items.length <= 1 ? items : [...new Set(items)];
313
396
  /**
314
397
  * Removes duplicate elements by comparing the result of a key function.
315
398
  *
399
+ * @see {@link uniq} for reference-equality deduplication.
400
+ * @see {@link uniqWith} for deduplicating with custom equality.
401
+ *
316
402
  * @example
317
403
  * ```ts
318
404
  * pipe(
@@ -321,14 +407,14 @@ const uniq = (data) => data.length <= 1 ? data : [...new Set(data)];
321
407
  * ); // [{id: 1, name: "a"}, {id: 2, name: "c"}]
322
408
  * ```
323
409
  */
324
- const uniqBy = (f) => (data) => {
410
+ const uniqBy = (keySelector) => (items) => {
325
411
  const seen = /* @__PURE__ */ new Set();
326
412
  const result = [];
327
- for (const a of data) {
328
- const key = f(a);
413
+ for (const item of items) {
414
+ const key = keySelector(item);
329
415
  if (!seen.has(key)) {
330
416
  seen.add(key);
331
- result.push(a);
417
+ result.push(item);
332
418
  }
333
419
  }
334
420
  return result;
@@ -338,6 +424,9 @@ const uniqBy = (f) => (data) => {
338
424
  * Preserves the order of first occurrences. Complements `uniq` (reference equality)
339
425
  * and `uniqBy` (key extraction).
340
426
  *
427
+ * @see {@link uniq} for reference-equality deduplication.
428
+ * @see {@link uniqBy} for key-based deduplication.
429
+ *
341
430
  * @example
342
431
  * ```ts
343
432
  * type Point = { x: number; y: number };
@@ -349,29 +438,33 @@ const uniqBy = (f) => (data) => {
349
438
  * ); // [{ x: 1, y: 1 }, { x: 2, y: 2 }]
350
439
  * ```
351
440
  */
352
- const uniqWith = (eq) => (data) => {
441
+ const uniqWith = (areEqual) => (items) => {
353
442
  const result = [];
354
- for (const a of data) if (!result.some((x) => eq(x, a))) result.push(a);
443
+ for (const item of items) if (!result.some((existing) => areEqual(existing, item))) result.push(item);
355
444
  return result;
356
445
  };
357
446
  /**
358
447
  * Sorts an array using a comparison function. Returns a new array.
359
448
  * To sort with a typed `Ordering<A>`, prefer `Arr.sortWith`.
360
449
  *
450
+ * @see {@link sortWith} for sorting using typed Ordering instances.
451
+ *
361
452
  * @example
362
453
  * ```ts
363
454
  * pipe([3, 1, 2], Arr.sortBy((a, b) => a - b)); // [1, 2, 3]
364
455
  * ```
365
456
  */
366
- const sortBy = (compare) => (data) => {
367
- const arr = data;
457
+ const sortBy = (compare) => (items) => {
458
+ const arr = items;
368
459
  if (typeof arr.toSorted === "function") return arr.toSorted(compare);
369
- return [...data].sort(compare);
460
+ return [...items].sort(compare);
370
461
  };
371
462
  /**
372
463
  * Sorts an array using an `Ordering<A>`. Returns a new array without mutating the original.
373
464
  * Use this over `sortBy` when you have a typed `Ordering<A>` from the `Ordering` module.
374
465
  *
466
+ * @see {@link sortBy} for sorting using a comparator function.
467
+ *
375
468
  * @example
376
469
  * ```ts
377
470
  * pipe([3, 1, 2], Arr.sortWith(Ordering.number)); // [1, 2, 3]
@@ -382,37 +475,41 @@ const sortBy = (compare) => (data) => {
382
475
  * pipe(products, Arr.sortWith(byPrice));
383
476
  * ```
384
477
  */
385
- const sortWith = (ord) => (data) => {
386
- const arr = data;
387
- if (typeof arr.toSorted === "function") return arr.toSorted(ord);
388
- return [...data].sort(ord);
478
+ const sortWith = (ordering) => (items) => {
479
+ const arr = items;
480
+ if (typeof arr.toSorted === "function") return arr.toSorted(ordering);
481
+ return [...items].sort(ordering);
389
482
  };
390
483
  /**
391
484
  * Pairs up elements from two arrays. Stops at the shorter array.
392
485
  *
486
+ * @see {@link zipWith} for pairing elements with a custom combining function.
487
+ *
393
488
  * @example
394
489
  * ```ts
395
490
  * pipe([1, 2, 3], Arr.zip(["a", "b"])); // [[1, "a"], [2, "b"]]
396
491
  * ```
397
492
  */
398
- const zip = (other) => (data) => {
399
- const len = Math.min(data.length, other.length);
493
+ const zip = (other) => (items) => {
494
+ const len = Math.min(items.length, other.length);
400
495
  const result = new Array(len);
401
- for (let i = 0; i < len; i++) result[i] = [data[i], other[i]];
496
+ for (let i = 0; i < len; i++) result[i] = [items[i], other[i]];
402
497
  return result;
403
498
  };
404
499
  /**
405
500
  * Combines elements from two arrays using a function. Stops at the shorter array.
406
501
  *
502
+ * @see {@link zip} for pairing elements into 2-tuples.
503
+ *
407
504
  * @example
408
505
  * ```ts
409
506
  * pipe([1, 2], Arr.zipWith((a: number, b: string) => `${a}${b}`)(["a", "b"])); // ["1a", "2b"]
410
507
  * ```
411
508
  */
412
- const zipWith = (f) => (other) => (data) => {
413
- const len = Math.min(data.length, other.length);
509
+ const zipWith = (combine) => (other) => (items) => {
510
+ const len = Math.min(items.length, other.length);
414
511
  const result = new Array(len);
415
- for (let i = 0; i < len; i++) result[i] = f(data[i], other[i]);
512
+ for (let i = 0; i < len; i++) result[i] = combine(items[i], other[i]);
416
513
  return result;
417
514
  };
418
515
  /**
@@ -423,10 +520,10 @@ const zipWith = (f) => (other) => (data) => {
423
520
  * pipe([1, 2, 3], Arr.intersperse(0)); // [1, 0, 2, 0, 3]
424
521
  * ```
425
522
  */
426
- const intersperse = (sep) => (data) => {
427
- if (data.length <= 1) return data;
428
- const result = [data[0]];
429
- for (let i = 1; i < data.length; i++) result.push(sep, data[i]);
523
+ const intersperse = (separator) => (items) => {
524
+ if (items.length <= 1) return items;
525
+ const result = [items[0]];
526
+ for (let i = 1; i < items.length; i++) result.push(separator, items[i]);
430
527
  return result;
431
528
  };
432
529
  /**
@@ -437,37 +534,41 @@ const intersperse = (sep) => (data) => {
437
534
  * pipe([1, 2], Arr.concat([3, 4])); // [1, 2, 3, 4]
438
535
  * ```
439
536
  */
440
- const concat = (other) => (data) => [...data, ...other];
537
+ const concat = (other) => (items) => [...items, ...other];
441
538
  /**
442
539
  * Splits an array into chunks of the given size.
443
540
  *
541
+ * @see {@link chunkBy} for grouping consecutive elements sharing a key.
542
+ *
444
543
  * @example
445
544
  * ```ts
446
545
  * pipe([1, 2, 3, 4, 5], Arr.chunksOf(2)); // [[1, 2], [3, 4], [5]]
447
546
  * ```
448
547
  */
449
- const chunksOf = (n) => (data) => {
450
- if (n <= 0) return [];
548
+ const chunksOf = (size) => (items) => {
549
+ if (size <= 0) return [];
451
550
  const result = [];
452
- for (let i = 0; i < data.length; i += n) result.push(data.slice(i, i + n));
551
+ for (let i = 0; i < items.length; i += size) result.push(items.slice(i, i + size));
453
552
  return result;
454
553
  };
455
554
  /**
456
555
  * Flattens a nested array by one level.
457
556
  *
557
+ * @see {@link flatMap} for mapping elements to arrays before flattening.
558
+ *
458
559
  * @example
459
560
  * ```ts
460
561
  * Arr.flatten([[1, 2], [3], [4, 5]]); // [1, 2, 3, 4, 5]
461
562
  * ```
462
563
  */
463
- const flatten = (data) => {
564
+ const flatten = (items) => {
464
565
  let totalLen = 0;
465
- const outerLen = data.length;
466
- for (let i = 0; i < outerLen; i++) totalLen += data[i].length;
566
+ const outerLen = items.length;
567
+ for (let i = 0; i < outerLen; i++) totalLen += items[i].length;
467
568
  const result = new Array(totalLen);
468
569
  let idx = 0;
469
570
  for (let i = 0; i < outerLen; i++) {
470
- const chunk = data[i];
571
+ const chunk = items[i];
471
572
  const innerLen = chunk.length;
472
573
  for (let j = 0; j < innerLen; j++) result[idx++] = chunk[j];
473
574
  }
@@ -476,16 +577,19 @@ const flatten = (data) => {
476
577
  /**
477
578
  * Maps each element to an array and flattens the result.
478
579
  *
580
+ * @see {@link map} for mapping without flattening.
581
+ * @see {@link flatten} for flattening without mapping.
582
+ *
479
583
  * @example
480
584
  * ```ts
481
585
  * pipe([1, 2, 3], Arr.flatMap(n => [n, n * 10])); // [1, 10, 2, 20, 3, 30]
482
586
  * ```
483
587
  */
484
- const flatMap = (f) => (data) => {
485
- const n = data.length;
588
+ const flatMap = (transform) => (items) => {
589
+ const n = items.length;
486
590
  const result = [];
487
591
  for (let i = 0; i < n; i++) {
488
- const chunk = f(data[i]);
592
+ const chunk = transform(items[i]);
489
593
  const m = chunk.length;
490
594
  for (let j = 0; j < m; j++) result.push(chunk[j]);
491
595
  }
@@ -494,32 +598,38 @@ const flatMap = (f) => (data) => {
494
598
  /**
495
599
  * Reduces an array from the left.
496
600
  *
601
+ * @see {@link scan} for preserving intermediate accumulation states.
602
+ *
497
603
  * @example
498
604
  * ```ts
499
605
  * pipe([1, 2, 3], Arr.reduce(0, (acc, n) => acc + n)); // 6
500
606
  * ```
501
607
  */
502
- const reduce$2 = (initial, f) => (data) => data.reduce(f, initial);
503
- const _traverseTask = Object.assign((f) => ArrTask.traverse(f), { Result: ArrTaskResult.traverse });
608
+ const reduce$2 = (initial, reducer) => (items) => items.reduce(reducer, initial);
609
+ const _traverseTask = Object.assign((f, options) => ArrTask.traverse(f, options), { Result: ArrTaskResult.traverse });
504
610
  const _sequenceTask = Object.assign((data) => ArrTask.sequence(data), { Result: ArrTaskResult.sequence });
505
611
  /**
506
612
  * Prepends a value to the beginning of an array, returning a NonEmptyArr.
507
613
  *
614
+ * @see {@link append} for adding an element to the end.
615
+ *
508
616
  * @example
509
617
  * ```ts
510
618
  * pipe([1, 2], Arr.prepend(0)); // [0, 1, 2]
511
619
  * ```
512
620
  */
513
- const prepend = (value) => (data) => [value, ...data];
621
+ const prepend = (item) => (items) => [item, ...items];
514
622
  /**
515
623
  * Appends a value to the end of an array, returning a NonEmptyArr.
516
624
  *
625
+ * @see {@link prepend} for adding an element to the beginning.
626
+ *
517
627
  * @example
518
628
  * ```ts
519
629
  * pipe([1, 2], Arr.append(3)); // [1, 2, 3]
520
630
  * ```
521
631
  */
522
- const append = (value) => (data) => [...data, value];
632
+ const append = (item) => (items) => [...items, item];
523
633
  /**
524
634
  * Returns the length of an array.
525
635
  *
@@ -528,31 +638,35 @@ const append = (value) => (data) => [...data, value];
528
638
  * Arr.size([1, 2, 3]); // 3
529
639
  * ```
530
640
  */
531
- const size$3 = (data) => data.length;
641
+ const size$3 = (items) => items.length;
532
642
  /**
533
643
  * Returns true if any element satisfies the predicate.
534
644
  *
645
+ * @see {@link every} for checking whether all elements satisfy a predicate.
646
+ *
535
647
  * @example
536
648
  * ```ts
537
649
  * pipe([1, 2, 3], Arr.some(n => n > 2)); // true
538
650
  * ```
539
651
  */
540
- const some = (predicate) => (data) => {
541
- const n = data.length;
542
- for (let i = 0; i < n; i++) if (predicate(data[i])) return true;
652
+ const some = (predicate) => (items) => {
653
+ const n = items.length;
654
+ for (let i = 0; i < n; i++) if (predicate(items[i])) return true;
543
655
  return false;
544
656
  };
545
657
  /**
546
658
  * Returns true if all elements satisfy the predicate.
547
659
  *
660
+ * @see {@link some} for checking whether any element satisfies a predicate.
661
+ *
548
662
  * @example
549
663
  * ```ts
550
664
  * pipe([1, 2, 3], Arr.every(n => n > 0)); // true
551
665
  * ```
552
666
  */
553
- const every = (predicate) => (data) => {
554
- const n = data.length;
555
- for (let i = 0; i < n; i++) if (!predicate(data[i])) return false;
667
+ const every = (predicate) => (items) => {
668
+ const n = items.length;
669
+ for (let i = 0; i < n; i++) if (!predicate(items[i])) return false;
556
670
  return true;
557
671
  };
558
672
  /**
@@ -563,11 +677,13 @@ const every = (predicate) => (data) => {
563
677
  * Arr.reverse([1, 2, 3]); // [3, 2, 1]
564
678
  * ```
565
679
  */
566
- const reverse = (data) => [...data].toReversed();
680
+ const reverse = (items) => [...items].toReversed();
567
681
  /**
568
682
  * Returns a new array with `item` inserted before the element at `index`.
569
683
  * Negative indices are clamped to 0; indices beyond the array length append to the end.
570
684
  *
685
+ * @see {@link removeAt} for removing an element at an index.
686
+ *
571
687
  * @example
572
688
  * ```ts
573
689
  * pipe([1, 2, 3], Arr.insertAt(1, 99)); // [1, 99, 2, 3]
@@ -575,11 +691,11 @@ const reverse = (data) => [...data].toReversed();
575
691
  * pipe([1, 2, 3], Arr.insertAt(3, 99)); // [1, 2, 3, 99]
576
692
  * ```
577
693
  */
578
- const insertAt = (index, item) => (data) => {
579
- const i = Math.max(0, Math.min(index, data.length));
580
- const arr = data;
694
+ const insertAt = (index, item) => (items) => {
695
+ const i = Math.max(0, Math.min(index, items.length));
696
+ const arr = items;
581
697
  if (typeof arr.toSpliced === "function") return arr.toSpliced(i, 0, item);
582
- const result = [...data];
698
+ const result = [...items];
583
699
  result.splice(i, 0, item);
584
700
  return result;
585
701
  };
@@ -587,6 +703,8 @@ const insertAt = (index, item) => (data) => {
587
703
  * Returns a new array with the element at `index` removed.
588
704
  * Returns the original array unchanged if `index` is out of bounds.
589
705
  *
706
+ * @see {@link insertAt} for inserting an element at an index.
707
+ *
590
708
  * @example
591
709
  * ```ts
592
710
  * pipe([1, 2, 3], Arr.removeAt(1)); // [1, 3]
@@ -594,76 +712,90 @@ const insertAt = (index, item) => (data) => {
594
712
  * pipe([1, 2, 3], Arr.removeAt(5)); // [1, 2, 3]
595
713
  * ```
596
714
  */
597
- const removeAt = (index) => (data) => {
598
- if (index < 0 || index >= data.length) return data;
599
- const arr = data;
715
+ const removeAt = (index) => (items) => {
716
+ if (index < 0 || index >= items.length) return items;
717
+ const arr = items;
600
718
  if (typeof arr.toSpliced === "function") return arr.toSpliced(index, 1);
601
- const result = [...data];
719
+ const result = [...items];
602
720
  result.splice(index, 1);
603
721
  return result;
604
722
  };
605
723
  /**
606
724
  * Takes the first n elements from an array.
607
725
  *
726
+ * @see {@link drop} for discarding the first n elements.
727
+ * @see {@link takeWhile} for taking elements based on a predicate.
728
+ *
608
729
  * @example
609
730
  * ```ts
610
731
  * pipe([1, 2, 3, 4], Arr.take(2)); // [1, 2]
611
732
  * ```
612
733
  */
613
- const take = (n) => (data) => n <= 0 ? [] : data.slice(0, n);
734
+ const take = (count) => (items) => count <= 0 ? [] : items.slice(0, count);
614
735
  /**
615
736
  * Drops the first n elements from an array.
616
737
  *
738
+ * @see {@link take} for keeping the first n elements.
739
+ * @see {@link dropWhile} for discarding elements based on a predicate.
740
+ *
617
741
  * @example
618
742
  * ```ts
619
743
  * pipe([1, 2, 3, 4], Arr.drop(2)); // [3, 4]
620
744
  * ```
621
745
  */
622
- const drop = (n) => (data) => data.slice(n);
746
+ const drop = (count) => (items) => items.slice(count);
623
747
  /**
624
748
  * Takes elements from the start while the predicate holds.
625
749
  *
750
+ * @see {@link dropWhile} for discarding elements while a predicate holds.
751
+ * @see {@link take} for taking a fixed count of elements.
752
+ *
626
753
  * @example
627
754
  * ```ts
628
755
  * pipe([1, 2, 3, 1], Arr.takeWhile(n => n < 3)); // [1, 2]
629
756
  * ```
630
757
  */
631
- const takeWhile = (predicate) => (data) => {
758
+ const takeWhile = (predicate) => (items) => {
632
759
  const result = [];
633
- for (const a of data) {
634
- if (!predicate(a)) break;
635
- result.push(a);
760
+ for (const item of items) {
761
+ if (!predicate(item)) break;
762
+ result.push(item);
636
763
  }
637
764
  return result;
638
765
  };
639
766
  /**
640
767
  * Drops elements from the start while the predicate holds.
641
768
  *
769
+ * @see {@link takeWhile} for keeping elements while a predicate holds.
770
+ * @see {@link drop} for discarding a fixed count of elements.
771
+ *
642
772
  * @example
643
773
  * ```ts
644
774
  * pipe([1, 2, 3, 1], Arr.dropWhile(n => n < 3)); // [3, 1]
645
775
  * ```
646
776
  */
647
- const dropWhile = (predicate) => (data) => {
777
+ const dropWhile = (predicate) => (items) => {
648
778
  let i = 0;
649
- while (i < data.length && predicate(data[i])) i++;
650
- return data.slice(i);
779
+ while (i < items.length && predicate(items[i])) i++;
780
+ return items.slice(i);
651
781
  };
652
782
  /**
653
783
  * Like `reduce`, but returns every intermediate accumulator as an array.
654
784
  * The initial value is not included — the output has the same length as the input.
655
785
  *
786
+ * @see {@link reduce} for computing only the final accumulator value.
787
+ *
656
788
  * @example
657
789
  * ```ts
658
790
  * pipe([1, 2, 3], Arr.scan(0, (acc, n) => acc + n)); // [1, 3, 6]
659
791
  * ```
660
792
  */
661
- const scan = (initial, f) => (data) => {
662
- const n = data.length;
793
+ const scan = (initial, reducer) => (items) => {
794
+ const n = items.length;
663
795
  const result = new Array(n);
664
796
  let acc = initial;
665
797
  for (let i = 0; i < n; i++) {
666
- acc = f(acc, data[i]);
798
+ acc = reducer(acc, items[i]);
667
799
  result[i] = acc;
668
800
  }
669
801
  return result;
@@ -679,28 +811,31 @@ const scan = (initial, f) => (data) => {
679
811
  * pipe([1, 2, 3], Arr.splitAt(10)); // [[1, 2, 3], []]
680
812
  * ```
681
813
  */
682
- const splitAt = (index) => (data) => {
814
+ const splitAt = (index) => (items) => {
683
815
  const i = Math.max(0, index);
684
- return [data.slice(0, i), data.slice(i)];
816
+ return [items.slice(0, i), items.slice(i)];
685
817
  };
686
818
  /**
687
819
  * Partitions an array by applying a function returning `Maybe<B>`.
688
820
  * Elements returning `None` are gathered into `failures` (original `A` values);
689
821
  * elements returning `Some(b)` are gathered into `successes` (`B` values).
690
822
  *
823
+ * @see {@link partitionMap} for partitioning with a Result mapper.
824
+ * @see {@link partition} for partitioning with a boolean predicate.
825
+ *
691
826
  * @example
692
827
  * ```ts
693
828
  * const parseNumber = (s: string) => isNaN(Number(s)) ? Maybe.make.none() : Maybe.make.some(Number(s));
694
829
  * pipe(["1", "abc", "3"], Arr.partitionMaybe(parseNumber)); // [["abc"], [1, 3]]
695
830
  * ```
696
831
  */
697
- const partitionMaybe = (f) => (data) => {
832
+ const partitionMaybe = (transform) => (items) => {
698
833
  const failures = [];
699
834
  const successes = [];
700
- for (let i = 0; i < data.length; i++) {
701
- const res = f(data[i]);
835
+ for (let i = 0; i < items.length; i++) {
836
+ const res = transform(items[i]);
702
837
  if (res.kind === "Some") successes.push(res.value);
703
- else failures.push(data[i]);
838
+ else failures.push(items[i]);
704
839
  }
705
840
  return [failures, successes];
706
841
  };
@@ -715,13 +850,15 @@ const partitionMaybe = (f) => (data) => {
715
850
  * pipe([10, 20, 30], Arr.at(5)); // None
716
851
  * ```
717
852
  */
718
- const at = (index) => (data) => {
719
- const targetIndex = index < 0 ? data.length + index : index;
720
- if (targetIndex < 0 || targetIndex >= data.length) return Maybe.make.none();
721
- return Maybe.make.some(data[targetIndex]);
853
+ const at = (index) => (items) => {
854
+ const targetIndex = index < 0 ? items.length + index : index;
855
+ if (targetIndex < 0 || targetIndex >= items.length) return Maybe.make.none();
856
+ return Maybe.make.some(items[targetIndex]);
722
857
  };
723
858
  /**
724
- * Finds the first element in an array for which `f` returns `Some(b)`.
859
+ * Finds the first element in an array for which `transform` returns `Some(b)`.
860
+ *
861
+ * @see {@link findFirst} for finding elements with a boolean predicate.
725
862
  *
726
863
  * @example
727
864
  * ```ts
@@ -731,9 +868,9 @@ const at = (index) => (data) => {
731
868
  * ); // Some(1)
732
869
  * ```
733
870
  */
734
- const findMap = (f) => (data) => {
735
- for (let i = 0; i < data.length; i++) {
736
- const res = f(data[i]);
871
+ const findMap = (transform) => (items) => {
872
+ for (let i = 0; i < items.length; i++) {
873
+ const res = transform(items[i]);
737
874
  if (res.kind === "Some") return res;
738
875
  }
739
876
  return Maybe.make.none();
@@ -741,6 +878,8 @@ const findMap = (f) => (data) => {
741
878
  /**
742
879
  * Indexes elements of an array into a `ReadonlyMap<K, A>` using a key extraction function.
743
880
  *
881
+ * @see {@link groupBy} for grouping multiple items per key into arrays.
882
+ *
744
883
  * @example
745
884
  * ```ts
746
885
  * pipe(
@@ -749,9 +888,9 @@ const findMap = (f) => (data) => {
749
888
  * ); // ReadonlyMap { 1 => { id: 1, name: "Alice" }, 2 => { id: 2, name: "Bob" } }
750
889
  * ```
751
890
  */
752
- const indexBy = (keyFn) => (data) => {
891
+ const indexBy = (keySelector) => (items) => {
753
892
  const resultMap = new globalThis.Map();
754
- for (let i = 0; i < data.length; i++) resultMap.set(keyFn(data[i]), data[i]);
893
+ for (let i = 0; i < items.length; i++) resultMap.set(keySelector(items[i]), items[i]);
755
894
  return resultMap;
756
895
  };
757
896
  /**
@@ -763,16 +902,18 @@ const indexBy = (keyFn) => (data) => {
763
902
  * // ReadonlyMap { "a" => 3, "b" => 2, "c" => 1 }
764
903
  * ```
765
904
  */
766
- const frequencies = (data) => {
905
+ const frequencies = (items) => {
767
906
  const resultMap = new globalThis.Map();
768
- for (let i = 0; i < data.length; i++) {
769
- const item = data[i];
907
+ for (let i = 0; i < items.length; i++) {
908
+ const item = items[i];
770
909
  resultMap.set(item, (resultMap.get(item) ?? 0) + 1);
771
910
  }
772
911
  return resultMap;
773
912
  };
774
913
  /**
775
- * Groups consecutive elements that share the same key returned by `keyFn`.
914
+ * Groups consecutive elements that share the same key returned by `keySelector`.
915
+ *
916
+ * @see {@link chunksOf} for fixed-size chunking.
776
917
  *
777
918
  * @example
778
919
  * ```ts
@@ -782,14 +923,14 @@ const frequencies = (data) => {
782
923
  * ); // [[1, 1], [2], [3, 3], [1]]
783
924
  * ```
784
925
  */
785
- const chunkBy = (keyFn) => (data) => {
786
- if (data.length === 0) return [];
926
+ const chunkBy = (keySelector) => (items) => {
927
+ if (items.length === 0) return [];
787
928
  const result = [];
788
- let currentChunk = [data[0]];
789
- let currentKey = keyFn(data[0]);
790
- for (let i = 1; i < data.length; i++) {
791
- const item = data[i];
792
- const key = keyFn(item);
929
+ let currentChunk = [items[0]];
930
+ let currentKey = keySelector(items[0]);
931
+ for (let i = 1; i < items.length; i++) {
932
+ const item = items[i];
933
+ const key = keySelector(item);
793
934
  if (Object.is(key, currentKey)) currentChunk.push(item);
794
935
  else {
795
936
  result.push(currentChunk);
@@ -804,20 +945,22 @@ const chunkBy = (keyFn) => (data) => {
804
945
  * Removes consecutive duplicate elements.
805
946
  * An optional `Equality<A>` can be provided (defaults to `Object.is`).
806
947
  *
948
+ * @see {@link uniq} for deduplicating across the entire array.
949
+ *
807
950
  * @example
808
951
  * ```ts
809
952
  * Arr.dedupeAdjacent()([1, 1, 2, 2, 1, 3]); // [1, 2, 1, 3]
810
953
  * ```
811
954
  */
812
- const dedupeAdjacent = (eq = (a, b) => Object.is(a, b)) => (data) => {
813
- if (data.length === 0) return [];
814
- const result = [data[0]];
815
- for (let i = 1; i < data.length; i++) if (!eq(data[i], result[result.length - 1])) result.push(data[i]);
955
+ const dedupeAdjacent = (areEqual = (first, second) => Object.is(first, second)) => (items) => {
956
+ if (items.length === 0) return [];
957
+ const result = [items[0]];
958
+ for (let i = 1; i < items.length; i++) if (!areEqual(items[i], result[result.length - 1])) result.push(items[i]);
816
959
  return result;
817
960
  };
818
961
  /**
819
962
  * Produces a sliding window of `size` elements over an array, advancing by `step` (default `1`).
820
- * Returns an empty array if `size <= 0` or `size > data.length`.
963
+ * Returns an empty array if `size <= 0` or `size > items.length`.
821
964
  *
822
965
  * @example
823
966
  * ```ts
@@ -825,15 +968,15 @@ const dedupeAdjacent = (eq = (a, b) => Object.is(a, b)) => (data) => {
825
968
  * pipe([1, 2, 3, 4], Arr.windowed(2, { step: 2 })); // [[1, 2], [3, 4]]
826
969
  * ```
827
970
  */
828
- const windowed = (windowSize, options) => (data) => {
971
+ const windowed = (windowSize, options) => (items) => {
829
972
  const step = options?.step ?? 1;
830
- if (windowSize <= 0 || step <= 0 || data.length < windowSize) return [];
973
+ if (windowSize <= 0 || step <= 0 || items.length < windowSize) return [];
831
974
  const result = [];
832
- for (let i = 0; i <= data.length - windowSize; i += step) result.push(data.slice(i, i + windowSize));
975
+ for (let i = 0; i <= items.length - windowSize; i += step) result.push(items.slice(i, i + windowSize));
833
976
  return result;
834
977
  };
835
978
  /**
836
- * Generates an array from an initial seed state until `f` returns `None`.
979
+ * Generates an array from an initial seed state until `step` returns `None`.
837
980
  *
838
981
  * @example
839
982
  * ```ts
@@ -841,11 +984,11 @@ const windowed = (windowSize, options) => (data) => {
841
984
  * // [1, 2, 3]
842
985
  * ```
843
986
  */
844
- const unfold = (initial, f) => {
987
+ const unfold = (initial, step) => {
845
988
  const result = [];
846
989
  let currentState = initial;
847
990
  while (true) {
848
- const next = f(currentState);
991
+ const next = step(currentState);
849
992
  if (next.kind === "None") break;
850
993
  const [item, nextState] = next.value;
851
994
  result.push(item);
@@ -886,6 +1029,7 @@ const Arr = {
886
1029
  prepend,
887
1030
  append,
888
1031
  size: size$3,
1032
+ length: size$3,
889
1033
  some,
890
1034
  every,
891
1035
  reverse,
@@ -906,33 +1050,44 @@ const Arr = {
906
1050
  dedupeAdjacent,
907
1051
  windowed,
908
1052
  unfold,
909
- from: { Array: (data) => data.length > 0 ? Maybe.make.some(data) : Maybe.make.none() },
910
1053
  is: {
911
- empty: (data) => data.length === 0,
912
- nonEmpty: (data) => isNonEmptyArr(data)
1054
+ /**
1055
+ * Returns `true` when the array is empty.
1056
+ *
1057
+ * @see {@link nonEmpty} for checking if an array contains elements.
1058
+ */
1059
+ empty: (items) => items.length === 0,
1060
+ /**
1061
+ * Returns `true` when the array contains at least one element.
1062
+ *
1063
+ * @see {@link empty} for checking if an array is empty.
1064
+ */
1065
+ nonEmpty: (items) => isNonEmptyArr(items)
913
1066
  },
914
1067
  traverse: {
915
1068
  Maybe: ArrMaybe.traverse,
916
1069
  Result: ArrResult.traverse,
917
- Task: _traverseTask
1070
+ Task: _traverseTask,
1071
+ Validation: ArrValidation.traverse
918
1072
  },
919
1073
  sequence: {
920
1074
  Maybe: ArrMaybe.sequence,
921
1075
  Result: ArrResult.sequence,
922
- Task: _sequenceTask
1076
+ Task: _sequenceTask,
1077
+ Validation: ArrValidation.sequence
923
1078
  },
924
1079
  NonEmpty: {
925
- singleton: (value) => [value],
926
- from: { Array: (data) => isNonEmptyArr(data) ? Maybe.make.some(data) : Maybe.make.none() },
927
- head: (data) => data[0],
928
- last: (data) => data[data.length - 1],
929
- tail: (data) => data.slice(1),
930
- reduce: (f) => (data) => data.reduce(f),
931
- map: (f) => (data) => map$3(f)(data),
932
- mapWithIndex: (f) => (data) => mapWithIndex(f)(data),
933
- intersperse: (sep) => (data) => intersperse(sep)(data),
934
- concat: (other) => (data) => concat(other)(data),
935
- reverse: (data) => reverse(data)
1080
+ singleton: (item) => [item],
1081
+ from: { array: (items) => isNonEmptyArr(items) ? Maybe.make.some(items) : Maybe.make.none() },
1082
+ head: (items) => items[0],
1083
+ last: (items) => items[items.length - 1],
1084
+ tail: (items) => items.slice(1),
1085
+ reduce: (reducer) => (items) => items.reduce(reducer),
1086
+ map: (transform) => (items) => map$3(transform)(items),
1087
+ mapWithIndex: (transform) => (items) => mapWithIndex(transform)(items),
1088
+ intersperse: (separator) => (items) => intersperse(separator)(items),
1089
+ concat: (other) => (items) => concat(other)(items),
1090
+ reverse: (items) => reverse(items)
936
1091
  }
937
1092
  };
938
1093
  //#endregion
@@ -963,30 +1118,36 @@ const BigNum = {
963
1118
  * BigNum.is.zero(5n); // false
964
1119
  * ```
965
1120
  */
966
- zero: (b) => b === 0n,
1121
+ zero: (value) => value === 0n,
967
1122
  /**
968
1123
  * Returns `true` when the bigint is an even integer.
969
1124
  *
1125
+ * @see {@link BigNum.is.odd} to check if a bigint is odd.
1126
+ *
970
1127
  * @example
971
1128
  * ```ts
972
1129
  * BigNum.is.even(4n); // true
973
1130
  * BigNum.is.even(3n); // false
974
1131
  * ```
975
1132
  */
976
- even: (b) => b % 2n === 0n,
1133
+ even: (value) => value % 2n === 0n,
977
1134
  /**
978
1135
  * Returns `true` when the bigint is an odd integer.
979
1136
  *
1137
+ * @see {@link BigNum.is.even} to check if a bigint is even.
1138
+ *
980
1139
  * @example
981
1140
  * ```ts
982
1141
  * BigNum.is.odd(3n); // true
983
1142
  * BigNum.is.odd(4n); // false
984
1143
  * ```
985
1144
  */
986
- odd: (b) => b % 2n !== 0n,
1145
+ odd: (value) => value % 2n !== 0n,
987
1146
  /**
988
1147
  * Returns `true` when the bigint is strictly greater than zero (`0n`).
989
1148
  *
1149
+ * @see {@link BigNum.is.negative} to check if a bigint is less than zero.
1150
+ *
990
1151
  * @example
991
1152
  * ```ts
992
1153
  * BigNum.is.positive(5n); // true
@@ -994,10 +1155,12 @@ const BigNum = {
994
1155
  * BigNum.is.positive(-5n); // false
995
1156
  * ```
996
1157
  */
997
- positive: (b) => b > 0n,
1158
+ positive: (value) => value > 0n,
998
1159
  /**
999
1160
  * Returns `true` when the bigint is strictly less than zero (`0n`).
1000
1161
  *
1162
+ * @see {@link BigNum.is.positive} to check if a bigint is greater than zero.
1163
+ *
1001
1164
  * @example
1002
1165
  * ```ts
1003
1166
  * BigNum.is.negative(-5n); // true
@@ -1005,7 +1168,7 @@ const BigNum = {
1005
1168
  * BigNum.is.negative(5n); // false
1006
1169
  * ```
1007
1170
  */
1008
- negative: (b) => b < 0n
1171
+ negative: (value) => value < 0n
1009
1172
  },
1010
1173
  from: {
1011
1174
  /**
@@ -1017,10 +1180,10 @@ const BigNum = {
1017
1180
  * BigNum.from.string("abc"); // None
1018
1181
  * ```
1019
1182
  */
1020
- string: (s) => {
1183
+ string: (text) => {
1021
1184
  try {
1022
- if (s.trim() === "") return Maybe.make.none();
1023
- return Maybe.make.some(BigInt(s));
1185
+ if (text.trim() === "") return Maybe.make.none();
1186
+ return Maybe.make.some(BigInt(text));
1024
1187
  } catch {
1025
1188
  return Maybe.make.none();
1026
1189
  }
@@ -1034,9 +1197,9 @@ const BigNum = {
1034
1197
  * BigNum.from.number(3.14); // None
1035
1198
  * ```
1036
1199
  */
1037
- number: (n) => {
1038
- if (!Number.isInteger(n) || n < Number.MIN_SAFE_INTEGER || n > Number.MAX_SAFE_INTEGER) return Maybe.make.none();
1039
- return Maybe.make.some(BigInt(n));
1200
+ number: (value) => {
1201
+ if (!Number.isInteger(value) || value < Number.MIN_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) return Maybe.make.none();
1202
+ return Maybe.make.some(BigInt(value));
1040
1203
  }
1041
1204
  },
1042
1205
  to: {
@@ -1049,75 +1212,100 @@ const BigNum = {
1049
1212
  * BigNum.to.number(9007199254740993n); // None
1050
1213
  * ```
1051
1214
  */
1052
- number: (b) => {
1053
- if (b < BigInt(Number.MIN_SAFE_INTEGER) || b > BigInt(Number.MAX_SAFE_INTEGER)) return Maybe.make.none();
1054
- return Maybe.make.some(Number(b));
1215
+ number: (value) => {
1216
+ if (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) return Maybe.make.none();
1217
+ return Maybe.make.some(Number(value));
1055
1218
  } },
1056
1219
  /**
1057
- * Adds `b` to `a`. Data-last curried signature: `add(b)(a)` = `a + b`.
1220
+ * Adds `amount` to `value`. Data-last curried signature: `add(amount)(value)` = `value + amount`.
1221
+ *
1222
+ * @see {@link BigNum.subtract} to subtract an amount from a bigint.
1058
1223
  *
1059
1224
  * @example
1060
1225
  * ```ts
1061
1226
  * pipe(10n, BigNum.add(5n)); // 15n
1062
1227
  * ```
1063
1228
  */
1064
- add: (b) => (a) => a + b,
1229
+ add: (amount) => (value) => value + amount,
1065
1230
  /**
1066
- * Subtracts `b` from `a`. Data-last curried signature: `sub(b)(a)` = `a - b`.
1231
+ * Subtracts `amount` from `from`. Data-last curried signature: `subtract(amount)(from)` = `from - amount`.
1232
+ *
1233
+ * @see {@link BigNum.add} to add an amount to a bigint.
1067
1234
  *
1068
1235
  * @example
1069
1236
  * ```ts
1070
- * pipe(10n, BigNum.sub(3n)); // 7n
1237
+ * pipe(10n, BigNum.subtract(3n)); // 7n
1071
1238
  * ```
1072
1239
  */
1073
- sub: (b) => (a) => a - b,
1240
+ subtract: (amount) => (from) => from - amount,
1074
1241
  /**
1075
- * Multiplies `a` by `b`. Data-last curried signature: `mul(b)(a)` = `a * b`.
1242
+ * Multiplies `value` by `factor`. Data-last curried signature: `multiply(factor)(value)` = `value * factor`.
1243
+ *
1244
+ * @see {@link BigNum.divide} to divide a bigint by a divisor.
1076
1245
  *
1077
1246
  * @example
1078
1247
  * ```ts
1079
- * pipe(6n, BigNum.mul(7n)); // 42n
1248
+ * pipe(6n, BigNum.multiply(7n)); // 42n
1080
1249
  * ```
1081
1250
  */
1082
- mul: (b) => (a) => a * b,
1251
+ multiply: (factor) => (value) => value * factor,
1083
1252
  /**
1084
- * Divides `a` by `b`. Returns `None` if `b` is `0n`.
1253
+ * Divides `dividend` by `divisor`. Returns `None` if `divisor` is `0n`.
1254
+ *
1255
+ * @see {@link BigNum.multiply} to multiply a bigint by a factor.
1256
+ * @see {@link BigNum.remainder} to compute the division remainder.
1085
1257
  *
1086
1258
  * @example
1087
1259
  * ```ts
1088
- * pipe(20n, BigNum.div(4n)); // Some(5n)
1089
- * pipe(5n, BigNum.div(0n)); // None
1260
+ * pipe(20n, BigNum.divide(4n)); // Some(5n)
1261
+ * pipe(5n, BigNum.divide(0n)); // None
1090
1262
  * ```
1091
1263
  */
1092
- div: (b) => (a) => b === 0n ? Maybe.make.none() : Maybe.make.some(a / b),
1264
+ divide: (divisor) => (dividend) => divisor === 0n ? Maybe.make.none() : Maybe.make.some(dividend / divisor),
1093
1265
  /**
1094
- * Computes remainder of `a / b`. Returns `None` if `b` is `0n`.
1266
+ * Computes remainder of `dividend / divisor`. Returns `None` if `divisor` is `0n`.
1267
+ *
1268
+ * @see {@link BigNum.divide} for full division.
1095
1269
  *
1096
1270
  * @example
1097
1271
  * ```ts
1098
- * pipe(10n, BigNum.mod(3n)); // Some(1n)
1099
- * pipe(5n, BigNum.mod(0n)); // None
1272
+ * pipe(10n, BigNum.remainder(3n)); // Some(1n)
1273
+ * pipe(5n, BigNum.remainder(0n)); // None
1100
1274
  * ```
1101
1275
  */
1102
- mod: (b) => (a) => b === 0n ? Maybe.make.none() : Maybe.make.some(a % b),
1276
+ remainder: (divisor) => (dividend) => divisor === 0n ? Maybe.make.none() : Maybe.make.some(dividend % divisor),
1103
1277
  /**
1104
- * Clamps `a` between `min` and `max` (inclusive).
1278
+ * Clamps `value` between `min` and `max` (inclusive).
1105
1279
  *
1106
1280
  * @example
1107
1281
  * ```ts
1108
1282
  * pipe(150n, BigNum.clamp(0n, 100n)); // 100n
1109
1283
  * ```
1110
1284
  */
1111
- clamp: (min, max) => (a) => a < min ? min : a > max ? max : a,
1285
+ clamp: (min, max) => (value) => value < min ? min : value > max ? max : value,
1286
+ /**
1287
+ * Returns `true` when the bigint is between `min` and `max` (both inclusive).
1288
+ *
1289
+ * @see {@link BigNum.inRange} for half-open range checking [start, end).
1290
+ *
1291
+ * @example
1292
+ * ```ts
1293
+ * pipe(5n, BigNum.between(1n, 10n)); // true
1294
+ * pipe(0n, BigNum.between(1n, 10n)); // false
1295
+ * ```
1296
+ */
1297
+ between: (min, max) => (value) => value >= min && value <= max,
1112
1298
  /**
1113
- * Returns `true` if `a` is in the range `[start, end)` (inclusive start, exclusive end).
1299
+ * Returns `true` if `value` is in the range `[start, end)` (inclusive start, exclusive end).
1300
+ *
1301
+ * @see {@link BigNum.between} for fully closed range checking [min, max].
1114
1302
  *
1115
1303
  * @example
1116
1304
  * ```ts
1117
1305
  * pipe(5n, BigNum.inRange(1n, 10n)); // true
1118
1306
  * ```
1119
1307
  */
1120
- inRange: (start, end) => (a) => a >= start && a < end,
1308
+ inRange: (start, end) => (value) => value >= start && value < end,
1121
1309
  /**
1122
1310
  * Returns absolute value of a `bigint`.
1123
1311
  *
@@ -1126,65 +1314,69 @@ number: (b) => {
1126
1314
  * BigNum.abs(-42n); // 42n
1127
1315
  * ```
1128
1316
  */
1129
- abs: (a) => a < 0n ? -a : a,
1317
+ abs: (value) => value < 0n ? -value : value,
1130
1318
  /**
1131
- * Returns the minimum of `a` and `b`.
1319
+ * Returns the minimum of `value` and `other`.
1320
+ *
1321
+ * @see {@link BigNum.max} to determine the maximum value.
1132
1322
  *
1133
1323
  * @example
1134
1324
  * ```ts
1135
1325
  * pipe(10n, BigNum.min(5n)); // 5n
1136
1326
  * ```
1137
1327
  */
1138
- min: (b) => (a) => a < b ? a : b,
1328
+ min: (other) => (value) => value < other ? value : other,
1139
1329
  /**
1140
- * Returns the maximum of `a` and `b`.
1330
+ * Returns the maximum of `value` and `other`.
1331
+ *
1332
+ * @see {@link BigNum.min} to determine the minimum value.
1141
1333
  *
1142
1334
  * @example
1143
1335
  * ```ts
1144
1336
  * pipe(10n, BigNum.max(5n)); // 10n
1145
1337
  * ```
1146
1338
  */
1147
- max: (b) => (a) => a > b ? a : b
1339
+ max: (other) => (value) => value > other ? value : other
1148
1340
  };
1149
1341
  //#endregion
1150
1342
  //#region src/Data/Bool.ts
1151
- const isBoolean = (u) => typeof u === "boolean";
1152
- const isTrue = (u) => u === true;
1153
- const isFalse = (u) => u === false;
1154
- const isTruthy = (u) => Boolean(u);
1155
- const isFalsy = (u) => !u;
1156
- const not = (b) => !b;
1157
- const and = (that) => (self) => self && that;
1158
- const or = (that) => (self) => self || that;
1159
- const xor = (that) => (self) => self !== that;
1160
- const andLazy = (that) => (self) => self && that();
1161
- const orLazy = (that) => (self) => self || that();
1162
- const all = (booleans) => {
1163
- for (let i = 0; i < booleans.length; i++) if (!booleans[i]) return false;
1343
+ const isBoolean = (value) => typeof value === "boolean";
1344
+ const isTrue = (value) => value === true;
1345
+ const isFalse = (value) => value === false;
1346
+ const isTruthy = (value) => Boolean(value);
1347
+ const isFalsy = (value) => !value;
1348
+ const not = (condition) => !condition;
1349
+ const and = (that) => (condition) => condition && that;
1350
+ const or = (that) => (condition) => condition || that;
1351
+ const xor = (that) => (condition) => condition !== that;
1352
+ const andLazy = (that) => (condition) => condition && that();
1353
+ const orLazy = (that) => (condition) => condition || that();
1354
+ const all = (conditions) => {
1355
+ for (let i = 0; i < conditions.length; i++) if (!conditions[i]) return false;
1164
1356
  return true;
1165
1357
  };
1166
- const any = (booleans) => {
1167
- for (let i = 0; i < booleans.length; i++) if (booleans[i]) return true;
1358
+ const any = (conditions) => {
1359
+ for (let i = 0; i < conditions.length; i++) if (conditions[i]) return true;
1168
1360
  return false;
1169
1361
  };
1170
- const fold = (onFalse, onTrue) => (b) => b ? onTrue() : onFalse();
1171
- const match = (cases) => (b) => b ? cases.true() : cases.false();
1172
- const fromString = (s) => {
1173
- const trimmed = s.trim().toLowerCase();
1362
+ const fold = (onFalse, onTrue) => (condition) => condition ? onTrue() : onFalse();
1363
+ const match = (cases) => (condition) => condition ? cases.true() : cases.false();
1364
+ const fromString = (text) => {
1365
+ const trimmed = text.trim().toLowerCase();
1174
1366
  if (trimmed === "true") return Maybe.make.some(true);
1175
1367
  if (trimmed === "false") return Maybe.make.some(false);
1176
1368
  return Maybe.make.none();
1177
1369
  };
1178
- const fromNumber = (n) => {
1179
- if (n === 1) return Maybe.make.some(true);
1180
- if (n === 0) return Maybe.make.some(false);
1370
+ const fromNumber = (value) => {
1371
+ if (value === 1) return Maybe.make.some(true);
1372
+ if (value === 0) return Maybe.make.some(false);
1181
1373
  return Maybe.make.none();
1182
1374
  };
1183
1375
  const fromTruthy = (value) => Boolean(value);
1184
- const toMaybe = (onTrue) => (b) => b ? Maybe.make.some(onTrue()) : Maybe.make.none();
1185
- const toResult = (onErr, onOk) => (b) => b ? Result.make.ok(onOk()) : Result.make.err(onErr());
1186
- const toNumber = (b) => b ? 1 : 0;
1187
- const toString = (b) => b ? "true" : "false";
1376
+ const toMaybe = (onTrue) => (condition) => condition ? Maybe.make.some(onTrue()) : Maybe.make.none();
1377
+ const toResult = (onErr, onOk) => (condition) => condition ? Result.make.ok(onOk()) : Result.make.err(onErr());
1378
+ const toNumber = (condition) => condition ? 1 : 0;
1379
+ const toString = (condition) => condition ? "true" : "false";
1188
1380
  const Bool = {
1189
1381
  is: {
1190
1382
  /**
@@ -1202,6 +1394,8 @@ const Bool = {
1202
1394
  /**
1203
1395
  * Narrowing guard — checks if a value is strictly `true`.
1204
1396
  *
1397
+ * @see {@link Bool.is.false} to check if a value is strictly false.
1398
+ *
1205
1399
  * @example
1206
1400
  * ```ts
1207
1401
  * Bool.is.true(true); // true
@@ -1212,6 +1406,8 @@ const Bool = {
1212
1406
  /**
1213
1407
  * Narrowing guard — checks if a value is strictly `false`.
1214
1408
  *
1409
+ * @see {@link Bool.is.true} to check if a value is strictly true.
1410
+ *
1215
1411
  * @example
1216
1412
  * ```ts
1217
1413
  * Bool.is.false(false); // true
@@ -1222,6 +1418,8 @@ const Bool = {
1222
1418
  /**
1223
1419
  * Type guard — checks if a value is truthy (not `false`, `0`, `0n`, `""`, `null`, `undefined`, or `NaN`).
1224
1420
  *
1421
+ * @see {@link Bool.is.falsy} to check if a value is falsy.
1422
+ *
1225
1423
  * @example
1226
1424
  * ```ts
1227
1425
  * Bool.is.truthy("hello"); // true
@@ -1234,6 +1432,8 @@ const Bool = {
1234
1432
  /**
1235
1433
  * Type guard — checks if a value is falsy (`false`, `0`, `0n`, `""`, `null`, `undefined`, or `NaN`).
1236
1434
  *
1435
+ * @see {@link Bool.is.truthy} to check if a value is truthy.
1436
+ *
1237
1437
  * @example
1238
1438
  * ```ts
1239
1439
  * Bool.is.falsy(""); // true
@@ -1254,9 +1454,12 @@ const Bool = {
1254
1454
  */
1255
1455
  not,
1256
1456
  /**
1257
- * Logical AND combinator. Returns `true` only if both `self` and `that` are `true`.
1457
+ * Logical AND combinator. Returns `true` only if both `condition` and `that` are `true`.
1258
1458
  *
1259
- * Data-last: `pipe(self, Bool.and(that))`.
1459
+ * Data-last: `pipe(condition, Bool.and(that))`.
1460
+ *
1461
+ * @see {@link Bool.or} for logical OR combinator.
1462
+ * @see {@link Bool.andLazy} for short-circuiting lazy evaluation.
1260
1463
  *
1261
1464
  * @example
1262
1465
  * ```ts
@@ -1266,9 +1469,12 @@ const Bool = {
1266
1469
  */
1267
1470
  and,
1268
1471
  /**
1269
- * Logical OR combinator. Returns `true` if either `self` or `that` is `true`.
1472
+ * Logical OR combinator. Returns `true` if either `condition` or `that` is `true`.
1473
+ *
1474
+ * Data-last: `pipe(condition, Bool.or(that))`.
1270
1475
  *
1271
- * Data-last: `pipe(self, Bool.or(that))`.
1476
+ * @see {@link Bool.and} for logical AND combinator.
1477
+ * @see {@link Bool.orLazy} for short-circuiting lazy evaluation.
1272
1478
  *
1273
1479
  * @example
1274
1480
  * ```ts
@@ -1278,9 +1484,9 @@ const Bool = {
1278
1484
  */
1279
1485
  or,
1280
1486
  /**
1281
- * Logical XOR (exclusive OR) combinator. Returns `true` if exactly one of `self` and `that` is `true`.
1487
+ * Logical XOR (exclusive OR) combinator. Returns `true` if exactly one of `condition` and `that` is `true`.
1282
1488
  *
1283
- * Data-last: `pipe(self, Bool.xor(that))`.
1489
+ * Data-last: `pipe(condition, Bool.xor(that))`.
1284
1490
  *
1285
1491
  * @example
1286
1492
  * ```ts
@@ -1291,9 +1497,12 @@ const Bool = {
1291
1497
  xor,
1292
1498
  /**
1293
1499
  * Lazy logical AND combinator.
1294
- * If `self` is `false`, the `that` computation is never evaluated.
1500
+ * If `condition` is `false`, the `that` computation is never evaluated.
1295
1501
  *
1296
- * Data-last: `pipe(self, Bool.andLazy(that))`.
1502
+ * Data-last: `pipe(condition, Bool.andLazy(that))`.
1503
+ *
1504
+ * @see {@link Bool.orLazy} for lazy logical OR combinator.
1505
+ * @see {@link Bool.and} for strict logical AND evaluation.
1297
1506
  *
1298
1507
  * @example
1299
1508
  * ```ts
@@ -1306,9 +1515,12 @@ const Bool = {
1306
1515
  andLazy,
1307
1516
  /**
1308
1517
  * Lazy logical OR combinator.
1309
- * If `self` is `true`, the `that` computation is never evaluated.
1518
+ * If `condition` is `true`, the `that` computation is never evaluated.
1519
+ *
1520
+ * Data-last: `pipe(condition, Bool.orLazy(that))`.
1310
1521
  *
1311
- * Data-last: `pipe(self, Bool.orLazy(that))`.
1522
+ * @see {@link Bool.andLazy} for lazy logical AND combinator.
1523
+ * @see {@link Bool.or} for strict logical OR evaluation.
1312
1524
  *
1313
1525
  * @example
1314
1526
  * ```ts
@@ -1324,6 +1536,8 @@ const Bool = {
1324
1536
  * Returns `true` if every boolean is `true`, or for an empty array (vacuous truth).
1325
1537
  * Short-circuits on the first `false`.
1326
1538
  *
1539
+ * @see {@link Bool.any} to check if at least one boolean is true.
1540
+ *
1327
1541
  * @example
1328
1542
  * ```ts
1329
1543
  * Bool.all([true, true, true]); // true
@@ -1337,6 +1551,8 @@ const Bool = {
1337
1551
  * Returns `true` if at least one boolean is `true`. Returns `false` for an empty array.
1338
1552
  * Short-circuits on the first `true`.
1339
1553
  *
1554
+ * @see {@link Bool.all} to check if all booleans are true.
1555
+ *
1340
1556
  * @example
1341
1557
  * ```ts
1342
1558
  * Bool.any([false, true, false]); // true
@@ -1351,6 +1567,8 @@ const Bool = {
1351
1567
  * Positional ordering: `onFalse` first, `onTrue` second.
1352
1568
  * Aligned with `Result.fold(onErr, onOk)` and `Maybe.fold(onNone, onSome)`.
1353
1569
  *
1570
+ * @see {@link Bool.match} for named-case pattern matching with an object literal.
1571
+ *
1354
1572
  * @example
1355
1573
  * ```ts
1356
1574
  * pipe(
@@ -1366,6 +1584,8 @@ const Bool = {
1366
1584
  /**
1367
1585
  * Pattern matching on boolean using named cases `{ true, false }`.
1368
1586
  *
1587
+ * @see {@link Bool.fold} for positional argument pattern matching.
1588
+ *
1369
1589
  * @example
1370
1590
  * ```ts
1371
1591
  * pipe(
@@ -1470,119 +1690,221 @@ const Bool = {
1470
1690
  //#endregion
1471
1691
  //#region src/Data/Dict.ts
1472
1692
  const DictIs = {
1473
- empty: (m) => m.size === 0,
1474
- nonEmpty: (m) => m.size > 0
1693
+ /**
1694
+ * Returns `true` when the dictionary contains zero entries.
1695
+ *
1696
+ * @see {@link nonEmpty} for checking if a dictionary contains entries.
1697
+ */
1698
+ empty: (dict) => dict.size === 0,
1699
+ /**
1700
+ * Returns `true` when the dictionary contains at least one entry.
1701
+ *
1702
+ * @see {@link empty} for checking if a dictionary is empty.
1703
+ */
1704
+ nonEmpty: (dict) => dict.size > 0
1475
1705
  };
1476
1706
  const empty$1 = () => new globalThis.Map();
1477
1707
  const singleton$1 = (key, value) => new globalThis.Map([[key, value]]);
1478
1708
  const DictFrom = {
1479
1709
  entries: (entries) => new globalThis.Map(entries),
1480
- Record: (record) => new globalThis.Map(Object.entries(record)),
1481
- Array: (data) => new globalThis.Map(data),
1482
- nullable: (data) => data === null || data === void 0 ? Maybe.make.none() : Maybe.make.some(data)
1710
+ record: (record) => new globalThis.Map(Object.entries(record)),
1711
+ nullable: (dict) => dict === null || dict === void 0 ? Maybe.make.none() : Maybe.make.some(dict)
1483
1712
  };
1484
- const DictTo = { Record: (map) => {
1713
+ const DictTo = { record: (dict) => {
1485
1714
  const result = {};
1486
- for (const [k, v] of map) result[k] = v;
1715
+ for (const [k, v] of dict) result[k] = v;
1487
1716
  return result;
1488
1717
  } };
1489
- const groupBy$1 = (f) => (as) => {
1718
+ const groupBy$1 = (keySelector) => (items) => {
1490
1719
  const result = new globalThis.Map();
1491
- for (const a of as) {
1492
- const k = f(a);
1720
+ for (const item of items) {
1721
+ const k = keySelector(item);
1493
1722
  const existing = result.get(k);
1494
- if (existing !== void 0) existing.push(a);
1495
- else result.set(k, [a]);
1723
+ if (existing !== void 0) existing.push(item);
1724
+ else result.set(k, [item]);
1496
1725
  }
1497
1726
  return result;
1498
1727
  };
1499
- const has$1 = (key) => (data) => data.has(key);
1500
- const lookup$1 = (key) => (data) => {
1501
- const val = data.get(key);
1502
- return val !== void 0 || data.has(key) ? Maybe.make.some(val) : Maybe.make.none();
1503
- };
1504
- const size$2 = (data) => data.size;
1505
- const keys$1 = (data) => Array.from(data.keys());
1506
- const values$1 = (data) => Array.from(data.values());
1507
- const entries$1 = (data) => Array.from(data.entries());
1508
- const insert = (key, value) => (data) => {
1509
- const res = new globalThis.Map(data);
1728
+ /**
1729
+ * Returns `true` when the dictionary contains the specified key.
1730
+ *
1731
+ * @see {@link lookup} for retrieving the value associated with a key.
1732
+ */
1733
+ const has$1 = (key) => (dict) => dict.has(key);
1734
+ /**
1735
+ * Retrieves the value associated with a key wrapped in a `Maybe`.
1736
+ *
1737
+ * @see {@link has} for checking key existence without retrieving the value.
1738
+ */
1739
+ const lookup$1 = (key) => (dict) => {
1740
+ const val = dict.get(key);
1741
+ return val !== void 0 || dict.has(key) ? Maybe.make.some(val) : Maybe.make.none();
1742
+ };
1743
+ const size$2 = (dict) => dict.size;
1744
+ /**
1745
+ * Returns all keys of a dictionary.
1746
+ *
1747
+ * @see {@link values} for extracting dictionary values.
1748
+ * @see {@link entries} for extracting key-value pairs.
1749
+ */
1750
+ const keys$1 = (dict) => Array.from(dict.keys());
1751
+ /**
1752
+ * Returns all values of a dictionary.
1753
+ *
1754
+ * @see {@link keys} for extracting dictionary keys.
1755
+ * @see {@link entries} for extracting key-value pairs.
1756
+ */
1757
+ const values$1 = (dict) => Array.from(dict.values());
1758
+ /**
1759
+ * Returns all key-value pairs of a dictionary.
1760
+ *
1761
+ * @see {@link keys} for extracting dictionary keys.
1762
+ * @see {@link values} for extracting dictionary values.
1763
+ */
1764
+ const entries$1 = (dict) => Array.from(dict.entries());
1765
+ /**
1766
+ * Returns a new dictionary with the key set to value.
1767
+ *
1768
+ * @see {@link remove} for deleting a key from a dictionary.
1769
+ * @see {@link upsert} for conditional insertion/update.
1770
+ */
1771
+ const insert = (key, value) => (dict) => {
1772
+ const res = new globalThis.Map(dict);
1510
1773
  res.set(key, value);
1511
1774
  return res;
1512
1775
  };
1513
- const remove$1 = (key) => (data) => {
1514
- if (!data.has(key)) return data;
1515
- const res = new globalThis.Map(data);
1776
+ /**
1777
+ * Returns a new dictionary with the specified key removed.
1778
+ *
1779
+ * @see {@link insert} for adding or replacing a key in a dictionary.
1780
+ */
1781
+ const remove$1 = (key) => (dict) => {
1782
+ if (!dict.has(key)) return dict;
1783
+ const res = new globalThis.Map(dict);
1516
1784
  res.delete(key);
1517
1785
  return res;
1518
1786
  };
1519
- const upsert = (key, f) => (data) => {
1520
- const res = new globalThis.Map(data);
1521
- const existing = data.has(key) ? Maybe.make.some(data.get(key)) : Maybe.make.none();
1522
- res.set(key, f(existing));
1787
+ /**
1788
+ * Inserts or updates a key using a callback that receives the existing value if present.
1789
+ *
1790
+ * @see {@link insert} for unconditional key setting.
1791
+ */
1792
+ const upsert = (key, update) => (dict) => {
1793
+ const res = new globalThis.Map(dict);
1794
+ const existing = dict.has(key) ? Maybe.make.some(dict.get(key)) : Maybe.make.none();
1795
+ res.set(key, update(existing));
1523
1796
  return res;
1524
1797
  };
1525
- const map$2 = (f) => (data) => {
1798
+ /**
1799
+ * Transforms each value in the dictionary.
1800
+ *
1801
+ * @see {@link mapWithKey} for transforming values with key access.
1802
+ */
1803
+ const map$2 = (transform) => (dict) => {
1526
1804
  const res = new globalThis.Map();
1527
- for (const [k, v] of data) res.set(k, f(v));
1805
+ for (const [k, v] of dict) res.set(k, transform(v));
1528
1806
  return res;
1529
1807
  };
1530
- const mapWithKey$1 = (f) => (data) => {
1808
+ /**
1809
+ * Transforms each value in the dictionary, also receiving the key.
1810
+ *
1811
+ * @see {@link map} for transforming values without key access.
1812
+ */
1813
+ const mapWithKey$1 = (transform) => (dict) => {
1531
1814
  const res = new globalThis.Map();
1532
- for (const [k, v] of data) res.set(k, f(k, v));
1815
+ for (const [k, v] of dict) res.set(k, transform(k, v));
1533
1816
  return res;
1534
1817
  };
1535
- const filter$2 = (predicate) => (data) => {
1818
+ /**
1819
+ * Filters dictionary entries by a predicate on values.
1820
+ *
1821
+ * @see {@link filterWithKey} for filtering with key access.
1822
+ */
1823
+ const filter$2 = (predicate) => (dict) => {
1536
1824
  const res = new globalThis.Map();
1537
- for (const [k, v] of data) if (predicate(v)) res.set(k, v);
1825
+ for (const [k, v] of dict) if (predicate(v)) res.set(k, v);
1538
1826
  return res;
1539
1827
  };
1540
- const filterWithKey$1 = (predicate) => (data) => {
1828
+ /**
1829
+ * Filters dictionary entries by a predicate that also receives the key.
1830
+ *
1831
+ * @see {@link filter} for filtering values without key access.
1832
+ */
1833
+ const filterWithKey$1 = (predicate) => (dict) => {
1541
1834
  const res = new globalThis.Map();
1542
- for (const [k, v] of data) if (predicate(k, v)) res.set(k, v);
1835
+ for (const [k, v] of dict) if (predicate(k, v)) res.set(k, v);
1543
1836
  return res;
1544
1837
  };
1545
- const compact$1 = (data) => {
1838
+ /**
1839
+ * Removes all `None` values from a dictionary, unwrapping `Some` values.
1840
+ */
1841
+ const compact$1 = (dict) => {
1546
1842
  const res = new globalThis.Map();
1547
- for (const [k, v] of data) if (v.kind === "Some") res.set(k, v.value);
1843
+ for (const [k, v] of dict) if (v.kind === "Some") res.set(k, v.value);
1548
1844
  return res;
1549
1845
  };
1550
- const filterMap$2 = (f) => (data) => {
1846
+ /**
1847
+ * Transforms values with a function returning `Maybe`, keeping only `Some` values.
1848
+ *
1849
+ * @see {@link filter} for filtering without transformation.
1850
+ */
1851
+ const filterMap$2 = (transform) => (dict) => {
1551
1852
  const res = new globalThis.Map();
1552
- for (const [k, v] of data) {
1553
- const mb = f(v);
1853
+ for (const [k, v] of dict) {
1854
+ const mb = transform(v);
1554
1855
  if (mb.kind === "Some") res.set(k, mb.value);
1555
1856
  }
1556
1857
  return res;
1557
1858
  };
1558
- const union$1 = (other) => (data) => {
1559
- if (data.size === 0) return other;
1560
- if (other.size === 0) return data;
1561
- const res = new globalThis.Map(data);
1859
+ /**
1860
+ * Combines two dictionaries, preferring entries from `other` on key collisions.
1861
+ *
1862
+ * @see {@link intersection} for keeping only common keys.
1863
+ * @see {@link difference} for removing keys present in the other dictionary.
1864
+ */
1865
+ const union$1 = (other) => (dict) => {
1866
+ if (dict.size === 0) return other;
1867
+ if (other.size === 0) return dict;
1868
+ const res = new globalThis.Map(dict);
1562
1869
  for (const [k, v] of other) res.set(k, v);
1563
1870
  return res;
1564
1871
  };
1565
- const intersection$1 = (other) => (data) => {
1872
+ /**
1873
+ * Returns a new dictionary containing only keys present in both dictionaries.
1874
+ *
1875
+ * @see {@link union} for combining all keys from both dictionaries.
1876
+ * @see {@link difference} for subtracting keys.
1877
+ */
1878
+ const intersection$1 = (other) => (dict) => {
1566
1879
  const res = new globalThis.Map();
1567
- for (const [k, v] of data) if (other.has(k)) res.set(k, v);
1880
+ for (const [k, v] of dict) if (other.has(k)) res.set(k, v);
1568
1881
  return res;
1569
1882
  };
1570
- const difference$1 = (other) => (data) => {
1571
- if (other.size === 0) return data;
1883
+ /**
1884
+ * Returns a new dictionary containing keys from `dict` that are not in `other`.
1885
+ *
1886
+ * @see {@link union} for combining all keys.
1887
+ * @see {@link intersection} for keeping only common keys.
1888
+ */
1889
+ const difference$1 = (other) => (dict) => {
1890
+ if (other.size === 0) return dict;
1572
1891
  const res = new globalThis.Map();
1573
- for (const [k, v] of data) if (!other.has(k)) res.set(k, v);
1892
+ for (const [k, v] of dict) if (!other.has(k)) res.set(k, v);
1574
1893
  return res;
1575
1894
  };
1576
- const reduce$1 = (init, f) => (data) => {
1577
- let acc = init;
1578
- for (const [, v] of data) acc = f(acc, v);
1895
+ const reduce$1 = (initial, reducer) => (dict) => {
1896
+ let acc = initial;
1897
+ for (const [, v] of dict) acc = reducer(acc, v);
1579
1898
  return acc;
1580
1899
  };
1581
- const reduceWithKey = (init, f) => (data) => {
1582
- let acc = init;
1583
- for (const [k, v] of data) acc = f(acc, v, k);
1900
+ const reduceWithKey = (initial, reducer) => (dict) => {
1901
+ let acc = initial;
1902
+ for (const [k, v] of dict) acc = reducer(acc, v, k);
1584
1903
  return acc;
1585
1904
  };
1905
+ /**
1906
+ * Merges two dictionaries using a combination function on collisions.
1907
+ */
1586
1908
  function mergeWith$1(combine) {
1587
1909
  return ((arg1, arg2) => {
1588
1910
  if (arg2 !== void 0) {
@@ -1600,27 +1922,27 @@ function mergeWith$1(combine) {
1600
1922
  };
1601
1923
  });
1602
1924
  }
1603
- const mapEntries$1 = (f) => (data) => {
1925
+ const mapEntries$1 = (transform) => (dict) => {
1604
1926
  const res = new globalThis.Map();
1605
- for (const [k, v] of data) {
1606
- const [nk, nv] = f(k, v);
1927
+ for (const [k, v] of dict) {
1928
+ const [nk, nv] = transform(k, v);
1607
1929
  res.set(nk, nv);
1608
1930
  }
1609
1931
  return res;
1610
1932
  };
1611
- const mapKeys$1 = (f) => (data) => {
1933
+ const mapKeys$1 = (transform) => (dict) => {
1612
1934
  const res = new globalThis.Map();
1613
- for (const [k, v] of data) res.set(f(k), v);
1935
+ for (const [k, v] of dict) res.set(transform(k), v);
1614
1936
  return res;
1615
1937
  };
1616
1938
  const _nonEmptySingleton = (key, value) => new globalThis.Map([[key, value]]);
1617
- const _nonEmptyFromMap = (m) => m.size > 0 ? Maybe.make.some(m) : Maybe.make.none();
1618
- const _nonEmptyKeys = (m) => keys$1(m);
1619
- const _nonEmptyValues = (m) => values$1(m);
1620
- const _nonEmptyEntries = (m) => entries$1(m);
1621
- const _nonEmptyReduce = (f) => (m) => _nonEmptyValues(m).reduce(f);
1622
- const _nonEmptyMap = (f) => (m) => map$2(f)(m);
1623
- const _nonEmptyMapWithKey = (f) => (m) => mapWithKey$1(f)(m);
1939
+ const _nonEmptyFromMap = (dict) => dict.size > 0 ? Maybe.make.some(dict) : Maybe.make.none();
1940
+ const _nonEmptyKeys = (dict) => keys$1(dict);
1941
+ const _nonEmptyValues = (dict) => values$1(dict);
1942
+ const _nonEmptyEntries = (dict) => entries$1(dict);
1943
+ const _nonEmptyReduce = (reducer) => (dict) => _nonEmptyValues(dict).reduce(reducer);
1944
+ const _nonEmptyMap = (transform) => (dict) => map$2(transform)(dict);
1945
+ const _nonEmptyMapWithKey = (transform) => (dict) => mapWithKey$1(transform)(dict);
1624
1946
  const Dict = {
1625
1947
  is: DictIs,
1626
1948
  empty: empty$1,
@@ -1653,7 +1975,7 @@ const Dict = {
1653
1975
  mapKeys: mapKeys$1,
1654
1976
  NonEmpty: {
1655
1977
  singleton: _nonEmptySingleton,
1656
- from: { Map: _nonEmptyFromMap },
1978
+ from: { map: _nonEmptyFromMap },
1657
1979
  keys: _nonEmptyKeys,
1658
1980
  values: _nonEmptyValues,
1659
1981
  entries: _nonEmptyEntries,
@@ -1706,9 +2028,9 @@ const Json = {
1706
2028
  };
1707
2029
  //#endregion
1708
2030
  //#region src/Data/Num.ts
1709
- const sumFn = (ns) => {
2031
+ const sumFn = (numbers) => {
1710
2032
  let result = 0;
1711
- for (let i = 0; i < ns.length; i++) result += ns[i];
2033
+ for (let i = 0; i < numbers.length; i++) result += numbers[i];
1712
2034
  return result;
1713
2035
  };
1714
2036
  const Num = {
@@ -1722,27 +2044,31 @@ const Num = {
1722
2044
  * Num.is.zero(5); // false
1723
2045
  * ```
1724
2046
  */
1725
- zero: (n) => n === 0,
2047
+ zero: (value) => value === 0,
1726
2048
  /**
1727
2049
  * Returns `true` when the number is a whole integer.
1728
2050
  *
2051
+ * @see {@link Num.is.float} to check for fractional numbers.
2052
+ *
1729
2053
  * @example
1730
2054
  * ```ts
1731
2055
  * Num.is.integer(5); // true
1732
2056
  * Num.is.integer(3.14); // false
1733
2057
  * ```
1734
2058
  */
1735
- integer: (n) => Number.isInteger(n),
2059
+ integer: (value) => Number.isInteger(value),
1736
2060
  /**
1737
2061
  * Returns `true` when the number is a finite float (fractional number).
1738
2062
  *
2063
+ * @see {@link Num.is.integer} to check for whole numbers.
2064
+ *
1739
2065
  * @example
1740
2066
  * ```ts
1741
2067
  * Num.is.float(3.14); // true
1742
2068
  * Num.is.float(5); // false
1743
2069
  * ```
1744
2070
  */
1745
- float: (n) => Number.isFinite(n) && !Number.isInteger(n),
2071
+ float: (value) => Number.isFinite(value) && !Number.isInteger(value),
1746
2072
  /**
1747
2073
  * Returns `true` when the number is finite (not `Infinity`, `-Infinity`, or `NaN`).
1748
2074
  *
@@ -1752,7 +2078,7 @@ const Num = {
1752
2078
  * Num.is.finite(Infinity); // false
1753
2079
  * ```
1754
2080
  */
1755
- finite: (n) => Number.isFinite(n),
2081
+ finite: (value) => Number.isFinite(value),
1756
2082
  /**
1757
2083
  * Returns `true` when the value is `NaN`.
1758
2084
  *
@@ -1762,10 +2088,12 @@ const Num = {
1762
2088
  * Num.is.nan(42); // false
1763
2089
  * ```
1764
2090
  */
1765
- nan: (n) => Number.isNaN(n),
2091
+ nan: (value) => Number.isNaN(value),
1766
2092
  /**
1767
2093
  * Returns `true` when the number is an even integer.
1768
2094
  *
2095
+ * @see {@link Num.is.odd} to check if a number is odd.
2096
+ *
1769
2097
  * @example
1770
2098
  * ```ts
1771
2099
  * Num.is.even(4); // true
@@ -1773,10 +2101,12 @@ const Num = {
1773
2101
  * Num.is.even(2.5); // false
1774
2102
  * ```
1775
2103
  */
1776
- even: (n) => Number.isInteger(n) && n % 2 === 0,
2104
+ even: (value) => Number.isInteger(value) && value % 2 === 0,
1777
2105
  /**
1778
2106
  * Returns `true` when the number is an odd integer.
1779
2107
  *
2108
+ * @see {@link Num.is.even} to check if a number is even.
2109
+ *
1780
2110
  * @example
1781
2111
  * ```ts
1782
2112
  * Num.is.odd(3); // true
@@ -1784,10 +2114,12 @@ const Num = {
1784
2114
  * Num.is.odd(2.5); // false
1785
2115
  * ```
1786
2116
  */
1787
- odd: (n) => Number.isInteger(n) && n % 2 !== 0,
2117
+ odd: (value) => Number.isInteger(value) && value % 2 !== 0,
1788
2118
  /**
1789
2119
  * Returns `true` when the number is strictly greater than zero.
1790
2120
  *
2121
+ * @see {@link Num.is.negative} to check if a number is less than zero.
2122
+ *
1791
2123
  * @example
1792
2124
  * ```ts
1793
2125
  * Num.is.positive(5); // true
@@ -1795,10 +2127,12 @@ const Num = {
1795
2127
  * Num.is.positive(-5); // false
1796
2128
  * ```
1797
2129
  */
1798
- positive: (n) => n > 0,
2130
+ positive: (value) => value > 0,
1799
2131
  /**
1800
2132
  * Returns `true` when the number is strictly less than zero.
1801
2133
  *
2134
+ * @see {@link Num.is.positive} to check if a number is greater than zero.
2135
+ *
1802
2136
  * @example
1803
2137
  * ```ts
1804
2138
  * Num.is.negative(-5); // true
@@ -1806,7 +2140,7 @@ const Num = {
1806
2140
  * Num.is.negative(5); // false
1807
2141
  * ```
1808
2142
  */
1809
- negative: (n) => n < 0
2143
+ negative: (value) => value < 0
1810
2144
  },
1811
2145
  /**
1812
2146
  * Generates an array of numbers from `from` to `to` (both inclusive),
@@ -1840,10 +2174,12 @@ const Num = {
1840
2174
  * pipe(42, Num.clamp(0, 100)); // 42
1841
2175
  * ```
1842
2176
  */
1843
- clamp: (min, max) => (n) => Math.min(Math.max(n, min), max),
2177
+ clamp: (min, max) => (value) => Math.min(Math.max(value, min), max),
1844
2178
  /**
1845
2179
  * Returns `true` when the number is between `min` and `max` (both inclusive).
1846
2180
  *
2181
+ * @see {@link Num.inRange} for half-open range checking [start, end).
2182
+ *
1847
2183
  * @example
1848
2184
  * ```ts
1849
2185
  * pipe(5, Num.between(1, 10)); // true
@@ -1851,10 +2187,12 @@ const Num = {
1851
2187
  * pipe(10, Num.between(1, 10)); // true
1852
2188
  * ```
1853
2189
  */
1854
- between: (min, max) => (n) => n >= min && n <= max,
2190
+ between: (min, max) => (value) => value >= min && value <= max,
1855
2191
  /**
1856
2192
  * Returns `true` when the number is in the range `[start, end)` (inclusive of `start`, exclusive of `end`).
1857
2193
  *
2194
+ * @see {@link Num.between} for fully closed range checking [min, max].
2195
+ *
1858
2196
  * @example
1859
2197
  * ```ts
1860
2198
  * pipe(5, Num.inRange(1, 10)); // true
@@ -1862,7 +2200,7 @@ const Num = {
1862
2200
  * pipe(10, Num.inRange(1, 10)); // false
1863
2201
  * ```
1864
2202
  */
1865
- inRange: (start, end) => (n) => n >= start && n < end,
2203
+ inRange: (start, end) => (value) => value >= start && value < end,
1866
2204
  /**
1867
2205
  * Parses a string as a number. Returns `None` when the result is `NaN`.
1868
2206
  *
@@ -1874,13 +2212,15 @@ const Num = {
1874
2212
  * Num.parse(""); // None
1875
2213
  * ```
1876
2214
  */
1877
- parse: (s) => {
1878
- if (s.trim() === "") return Maybe.make.none();
1879
- const n = Number(s);
2215
+ parse: (text) => {
2216
+ if (text.trim() === "") return Maybe.make.none();
2217
+ const n = Number(text);
1880
2218
  return isNaN(n) ? Maybe.make.none() : Maybe.make.some(n);
1881
2219
  },
1882
2220
  /**
1883
- * Adds `b` to a number. Data-last: use in `pipe` or `Arr.map`.
2221
+ * Adds `amount` to a number. Data-last: use in `pipe` or `Arr.map`.
2222
+ *
2223
+ * @see {@link Num.subtract} to subtract an amount from a number.
1884
2224
  *
1885
2225
  * @example
1886
2226
  * ```ts
@@ -1888,9 +2228,11 @@ const Num = {
1888
2228
  * pipe([1, 2, 3], Arr.map(Num.add(10))); // [11, 12, 13]
1889
2229
  * ```
1890
2230
  */
1891
- add: (b) => (a) => a + b,
2231
+ add: (amount) => (value) => value + amount,
1892
2232
  /**
1893
- * Subtracts `b` from a number. Data-last: `subtract(b)(a)` = `a - b`.
2233
+ * Subtracts `amount` from a number. Data-last: `subtract(amount)(from)` = `from - amount`.
2234
+ *
2235
+ * @see {@link Num.add} to add an amount to a number.
1894
2236
  *
1895
2237
  * @example
1896
2238
  * ```ts
@@ -1898,9 +2240,11 @@ const Num = {
1898
2240
  * pipe([5, 10, 15], Arr.map(Num.subtract(2))); // [3, 8, 13]
1899
2241
  * ```
1900
2242
  */
1901
- subtract: (b) => (a) => a - b,
2243
+ subtract: (amount) => (from) => from - amount,
1902
2244
  /**
1903
- * Multiplies a number by `b`. Data-last: use in `pipe` or `Arr.map`.
2245
+ * Multiplies a number by `factor`. Data-last: use in `pipe` or `Arr.map`.
2246
+ *
2247
+ * @see {@link Num.divide} to divide a number by a divisor.
1904
2248
  *
1905
2249
  * @example
1906
2250
  * ```ts
@@ -1908,9 +2252,12 @@ const Num = {
1908
2252
  * pipe([1, 2, 3], Arr.map(Num.multiply(100))); // [100, 200, 300]
1909
2253
  * ```
1910
2254
  */
1911
- multiply: (b) => (a) => a * b,
2255
+ multiply: (factor) => (value) => value * factor,
1912
2256
  /**
1913
- * Divides a number by `b`. Returns `None` when `b` is zero. Data-last: `divide(b)(a)` = `a / b`.
2257
+ * Divides a number by `divisor`. Returns `None` when `divisor` is zero. Data-last: `divide(divisor)(dividend)` = `dividend / divisor`.
2258
+ *
2259
+ * @see {@link Num.multiply} to multiply a number by a factor.
2260
+ * @see {@link Num.remainder} to compute the division remainder.
1914
2261
  *
1915
2262
  * @example
1916
2263
  * ```ts
@@ -1919,7 +2266,7 @@ const Num = {
1919
2266
  * pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
1920
2267
  * ```
1921
2268
  */
1922
- divide: (b) => (a) => b === 0 ? Maybe.make.none() : Maybe.make.some(a / b),
2269
+ divide: (divisor) => (dividend) => divisor === 0 ? Maybe.make.none() : Maybe.make.some(dividend / divisor),
1923
2270
  /**
1924
2271
  * Returns the absolute value of a number.
1925
2272
  *
@@ -1929,7 +2276,7 @@ const Num = {
1929
2276
  * pipe(5, Num.abs); // 5
1930
2277
  * ```
1931
2278
  */
1932
- abs: (n) => Math.abs(n),
2279
+ abs: (value) => Math.abs(value),
1933
2280
  /**
1934
2281
  * Negates a number (arithmetic negation).
1935
2282
  *
@@ -1939,40 +2286,51 @@ const Num = {
1939
2286
  * pipe(-5, Num.negate); // 5
1940
2287
  * ```
1941
2288
  */
1942
- negate: (n) => -n,
2289
+ negate: (value) => -value,
1943
2290
  /**
1944
2291
  * Rounds a number to the nearest integer.
1945
2292
  *
2293
+ * @see {@link Num.floor} to round down.
2294
+ * @see {@link Num.ceil} to round up.
2295
+ *
1946
2296
  * @example
1947
2297
  * ```ts
1948
2298
  * pipe(3.5, Num.round); // 4
1949
2299
  * pipe(3.4, Num.round); // 3
1950
2300
  * ```
1951
2301
  */
1952
- round: (n) => Math.round(n),
2302
+ round: (value) => Math.round(value),
1953
2303
  /**
1954
2304
  * Rounds a number down to the nearest integer.
1955
2305
  *
2306
+ * @see {@link Num.round} to round to nearest integer.
2307
+ * @see {@link Num.ceil} to round up.
2308
+ *
1956
2309
  * @example
1957
2310
  * ```ts
1958
2311
  * pipe(3.9, Num.floor); // 3
1959
2312
  * pipe(-3.2, Num.floor); // -4
1960
2313
  * ```
1961
2314
  */
1962
- floor: (n) => Math.floor(n),
2315
+ floor: (value) => Math.floor(value),
1963
2316
  /**
1964
2317
  * Rounds a number up to the nearest integer.
1965
2318
  *
2319
+ * @see {@link Num.round} to round to nearest integer.
2320
+ * @see {@link Num.floor} to round down.
2321
+ *
1966
2322
  * @example
1967
2323
  * ```ts
1968
2324
  * pipe(3.1, Num.ceil); // 4
1969
2325
  * pipe(-3.9, Num.ceil); // -3
1970
2326
  * ```
1971
2327
  */
1972
- ceil: (n) => Math.ceil(n),
2328
+ ceil: (value) => Math.ceil(value),
1973
2329
  /**
1974
2330
  * Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
1975
- * Data-last: `remainder(divisor)(a)` = `a % divisor`.
2331
+ * Data-last: `remainder(divisor)(dividend)` = `dividend % divisor`.
2332
+ *
2333
+ * @see {@link Num.divide} for full division.
1976
2334
  *
1977
2335
  * @example
1978
2336
  * ```ts
@@ -1981,7 +2339,7 @@ const Num = {
1981
2339
  * pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
1982
2340
  * ```
1983
2341
  */
1984
- remainder: (divisor) => (n) => divisor === 0 ? Maybe.make.none() : Maybe.make.some(n % divisor),
2342
+ remainder: (divisor) => (dividend) => divisor === 0 ? Maybe.make.none() : Maybe.make.some(dividend % divisor),
1985
2343
  /**
1986
2344
  * Computes the sum of a list of numbers. Returns `0` if the list is empty.
1987
2345
  *
@@ -2001,39 +2359,43 @@ const Num = {
2001
2359
  * Num.mean([]); // None
2002
2360
  * ```
2003
2361
  */
2004
- mean: (ns) => ns.length === 0 ? Maybe.make.none() : Maybe.make.some(sumFn(ns) / ns.length),
2362
+ mean: (numbers) => numbers.length === 0 ? Maybe.make.none() : Maybe.make.some(sumFn(numbers) / numbers.length),
2005
2363
  /**
2006
2364
  * Computes the minimum of a list of numbers. Returns `None` if the list is empty.
2007
2365
  *
2366
+ * @see {@link Num.max} to compute the maximum value.
2367
+ *
2008
2368
  * @example
2009
2369
  * ```ts
2010
2370
  * Num.min([5, 1, 3]); // Some(1)
2011
2371
  * Num.min([]); // None
2012
2372
  * ```
2013
2373
  */
2014
- min: (ns) => {
2015
- if (ns.length === 0) return Maybe.make.none();
2016
- let [result] = ns;
2017
- for (let i = 1; i < ns.length; i++) if (ns[i] < result) result = ns[i];
2374
+ min: (numbers) => {
2375
+ if (numbers.length === 0) return Maybe.make.none();
2376
+ let [result] = numbers;
2377
+ for (let i = 1; i < numbers.length; i++) if (numbers[i] < result) result = numbers[i];
2018
2378
  return Maybe.make.some(result);
2019
2379
  },
2020
2380
  /**
2021
2381
  * Computes the maximum of a list of numbers. Returns `None` if the list is empty.
2022
2382
  *
2383
+ * @see {@link Num.min} to compute the minimum value.
2384
+ *
2023
2385
  * @example
2024
2386
  * ```ts
2025
2387
  * Num.max([1, 5, 3]); // Some(5)
2026
2388
  * Num.max([]); // None
2027
2389
  * ```
2028
2390
  */
2029
- max: (ns) => {
2030
- if (ns.length === 0) return Maybe.make.none();
2031
- let [result] = ns;
2032
- for (let i = 1; i < ns.length; i++) if (ns[i] > result) result = ns[i];
2391
+ max: (numbers) => {
2392
+ if (numbers.length === 0) return Maybe.make.none();
2393
+ let [result] = numbers;
2394
+ for (let i = 1; i < numbers.length; i++) if (numbers[i] > result) result = numbers[i];
2033
2395
  return Maybe.make.some(result);
2034
2396
  },
2035
2397
  /**
2036
- * Formats a number using `Intl.NumberFormat`. Returns `None` when `n` is `NaN` or non-finite.
2398
+ * Formats a number using `Intl.NumberFormat`. Returns `None` when `value` is `NaN` or non-finite.
2037
2399
  * Data-last curried signature.
2038
2400
  *
2039
2401
  * @example
@@ -2043,11 +2405,11 @@ const Num = {
2043
2405
  * pipe(NaN, formatCurrency); // None
2044
2406
  * ```
2045
2407
  */
2046
- format: (options, locales) => (n) => !Number.isFinite(n) ? Maybe.make.none() : Maybe.make.some(new Intl.NumberFormat(locales, options).format(n))
2408
+ format: (options, locales) => (value) => !Number.isFinite(value) ? Maybe.make.none() : Maybe.make.some(new Intl.NumberFormat(locales, options).format(value))
2047
2409
  };
2048
2410
  //#endregion
2049
2411
  //#region src/Data/Rec.ts
2050
- const _isNonEmpty = (data) => Object.keys(data).length > 0;
2412
+ const _isNonEmpty = (record) => Object.keys(record).length > 0;
2051
2413
  const _setKey = (record, key, value) => {
2052
2414
  if (key === "__proto__") Object.defineProperty(record, key, {
2053
2415
  value,
@@ -2059,8 +2421,8 @@ const _setKey = (record, key, value) => {
2059
2421
  };
2060
2422
  let RecMaybe;
2061
2423
  (function(_RecMaybe) {
2062
- const traverse = _RecMaybe.traverse = (f) => (data) => {
2063
- const recordKeys = Object.keys(data);
2424
+ const traverse = _RecMaybe.traverse = (transform) => (record) => {
2425
+ const recordKeys = Object.keys(record);
2064
2426
  if (recordKeys.length === 0) return {
2065
2427
  kind: "Some",
2066
2428
  value: {}
@@ -2068,7 +2430,7 @@ let RecMaybe;
2068
2430
  const result = {};
2069
2431
  for (let i = 0; i < recordKeys.length; i++) {
2070
2432
  const key = recordKeys[i];
2071
- const maybeVal = f(data[key]);
2433
+ const maybeVal = transform(record[key]);
2072
2434
  if (maybeVal.kind === "None") return maybeVal;
2073
2435
  _setKey(result, key, maybeVal.value);
2074
2436
  }
@@ -2077,16 +2439,16 @@ let RecMaybe;
2077
2439
  value: result
2078
2440
  };
2079
2441
  };
2080
- _RecMaybe.sequence = (data) => traverse((a) => a)(data);
2442
+ _RecMaybe.sequence = (record) => traverse((value) => value)(record);
2081
2443
  })(RecMaybe || (RecMaybe = {}));
2082
2444
  let RecResult;
2083
2445
  (function(_RecResult) {
2084
- const traverse = _RecResult.traverse = (f) => (data) => {
2085
- const recordKeys = Object.keys(data);
2446
+ const traverse = _RecResult.traverse = (transform) => (record) => {
2447
+ const recordKeys = Object.keys(record);
2086
2448
  const result = {};
2087
2449
  for (let i = 0; i < recordKeys.length; i++) {
2088
2450
  const key = recordKeys[i];
2089
- const res = f(data[key]);
2451
+ const res = transform(record[key]);
2090
2452
  if (res.kind === "Err") return res;
2091
2453
  _setKey(result, key, res.value);
2092
2454
  }
@@ -2095,7 +2457,7 @@ let RecResult;
2095
2457
  value: result
2096
2458
  };
2097
2459
  };
2098
- _RecResult.sequence = (data) => traverse((a) => a)(data);
2460
+ _RecResult.sequence = (record) => traverse((value) => value)(record);
2099
2461
  })(RecResult || (RecResult = {}));
2100
2462
  /**
2101
2463
  * Functional record/object utilities that compose well with pipe.
@@ -2117,16 +2479,20 @@ const RecIs = {
2117
2479
  /**
2118
2480
  * Returns true if the record has no keys.
2119
2481
  *
2482
+ * @see {@link nonEmpty} for checking if a record has keys.
2483
+ *
2120
2484
  * @example
2121
2485
  * ```ts
2122
2486
  * Rec.is.empty({}); // true
2123
2487
  * Rec.is.empty({ a: 1 }); // false
2124
2488
  * ```
2125
2489
  */
2126
- empty: (data) => Object.keys(data).length === 0,
2490
+ empty: (record) => Object.keys(record).length === 0,
2127
2491
  /**
2128
2492
  * Type guard to check if a record is non-empty.
2129
2493
  *
2494
+ * @see {@link empty} for checking if a record has no keys.
2495
+ *
2130
2496
  * @example
2131
2497
  * ```ts
2132
2498
  * Rec.is.nonEmpty({ a: 1 }); // true
@@ -2138,30 +2504,36 @@ const RecIs = {
2138
2504
  /**
2139
2505
  * Transforms each value in a record.
2140
2506
  *
2507
+ * @see {@link mapWithKey} for transforming values with key access.
2508
+ * @see {@link mapKeys} for transforming keys while preserving values.
2509
+ * @see {@link mapEntries} for transforming keys and values simultaneously.
2510
+ *
2141
2511
  * @example
2142
2512
  * ```ts
2143
2513
  * pipe({ a: 1, b: 2 }, Rec.map(n => n * 2)); // { a: 2, b: 4 }
2144
2514
  * ```
2145
2515
  */
2146
- const map$1 = (f) => (data) => {
2147
- const recordKeys = Object.keys(data);
2148
- const recordValues = Object.values(data);
2149
- const result = Object.create(Object.getPrototypeOf(data));
2516
+ const map$1 = (transform) => (record) => {
2517
+ const recordKeys = Object.keys(record);
2518
+ const recordValues = Object.values(record);
2519
+ const result = Object.create(Object.getPrototypeOf(record));
2150
2520
  for (let i = 0; i < recordKeys.length; i++) {
2151
2521
  const key = recordKeys[i];
2152
2522
  if (key === "__proto__") Object.defineProperty(result, "__proto__", {
2153
- value: f(recordValues[i]),
2523
+ value: transform(recordValues[i]),
2154
2524
  writable: true,
2155
2525
  enumerable: true,
2156
2526
  configurable: true
2157
2527
  });
2158
- else result[key] = f(recordValues[i]);
2528
+ else result[key] = transform(recordValues[i]);
2159
2529
  }
2160
2530
  return result;
2161
2531
  };
2162
2532
  /**
2163
2533
  * Maps each value in a record with a function returning a `Maybe`, keeping only `Some` values.
2164
2534
  *
2535
+ * @see {@link filter} for filtering with a boolean predicate.
2536
+ *
2165
2537
  * @example
2166
2538
  * ```ts
2167
2539
  * pipe(
@@ -2170,12 +2542,12 @@ const map$1 = (f) => (data) => {
2170
2542
  * ); // { b: 20 }
2171
2543
  * ```
2172
2544
  */
2173
- const filterMap$1 = (f) => (data) => {
2174
- const recordKeys = Object.keys(data);
2175
- const recordValues = Object.values(data);
2176
- const result = Object.create(Object.getPrototypeOf(data));
2545
+ const filterMap$1 = (transform) => (record) => {
2546
+ const recordKeys = Object.keys(record);
2547
+ const recordValues = Object.values(record);
2548
+ const result = Object.create(Object.getPrototypeOf(record));
2177
2549
  for (let i = 0; i < recordKeys.length; i++) {
2178
- const maybeVal = f(recordValues[i]);
2550
+ const maybeVal = transform(recordValues[i]);
2179
2551
  if (maybeVal.kind === "Some") _setKey(result, recordKeys[i], maybeVal.value);
2180
2552
  }
2181
2553
  return result;
@@ -2183,49 +2555,56 @@ const filterMap$1 = (f) => (data) => {
2183
2555
  /**
2184
2556
  * Transforms each value in a record, also receiving the key.
2185
2557
  *
2558
+ * @see {@link map} for transforming values without key access.
2559
+ *
2186
2560
  * @example
2187
2561
  * ```ts
2188
2562
  * pipe({ a: 1, b: 2 }, Rec.mapWithKey((k, v) => `${k}:${v}`));
2189
2563
  * // { a: "a:1", b: "b:2" }
2190
2564
  * ```
2191
2565
  */
2192
- const mapWithKey = (f) => (data) => {
2193
- const recordKeys = Object.keys(data);
2194
- const recordValues = Object.values(data);
2195
- const result = Object.create(Object.getPrototypeOf(data));
2566
+ const mapWithKey = (transform) => (record) => {
2567
+ const recordKeys = Object.keys(record);
2568
+ const recordValues = Object.values(record);
2569
+ const result = Object.create(Object.getPrototypeOf(record));
2196
2570
  for (let i = 0; i < recordKeys.length; i++) {
2197
2571
  const key = recordKeys[i];
2198
- _setKey(result, key, f(key, recordValues[i]));
2572
+ _setKey(result, key, transform(key, recordValues[i]));
2199
2573
  }
2200
2574
  return result;
2201
2575
  };
2202
2576
  /**
2203
2577
  * Filters values in a record by a predicate.
2204
2578
  *
2579
+ * @see {@link filterWithKey} for filtering values with key access.
2580
+ * @see {@link filterMap} for filtering and mapping in a single pass.
2581
+ *
2205
2582
  * @example
2206
2583
  * ```ts
2207
2584
  * pipe({ a: 1, b: 2, c: 3 }, Rec.filter(n => n > 1)); // { b: 2, c: 3 }
2208
2585
  * ```
2209
2586
  */
2210
- const filter$1 = (predicate) => (data) => {
2211
- const recordKeys = Object.keys(data);
2212
- const recordValues = Object.values(data);
2213
- const result = Object.create(Object.getPrototypeOf(data));
2587
+ const filter$1 = (predicate) => (record) => {
2588
+ const recordKeys = Object.keys(record);
2589
+ const recordValues = Object.values(record);
2590
+ const result = Object.create(Object.getPrototypeOf(record));
2214
2591
  for (let i = 0; i < recordKeys.length; i++) if (predicate(recordValues[i])) _setKey(result, recordKeys[i], recordValues[i]);
2215
2592
  return result;
2216
2593
  };
2217
2594
  /**
2218
2595
  * Filters values in a record by a predicate that also receives the key.
2219
2596
  *
2597
+ * @see {@link filter} for filtering values without key access.
2598
+ *
2220
2599
  * @example
2221
2600
  * ```ts
2222
2601
  * pipe({ a: 1, b: 2, c: 3 }, Rec.filterWithKey((k, v) => k !== "a" && v > 0));
2223
2602
  * // { b: 2 }
2224
2603
  * ```
2225
2604
  */
2226
- const filterWithKey = (predicate) => (data) => {
2605
+ const filterWithKey = (predicate) => (record) => {
2227
2606
  const result = {};
2228
- for (const [k, v] of Object.entries(data)) if (predicate(k, v)) _setKey(result, k, v);
2607
+ for (const [k, v] of Object.entries(record)) if (predicate(k, v)) _setKey(result, k, v);
2229
2608
  return result;
2230
2609
  };
2231
2610
  /**
@@ -2237,37 +2616,46 @@ const filterWithKey = (predicate) => (data) => {
2237
2616
  * pipe({ a: 1, b: 2 }, Rec.lookup("c")); // None
2238
2617
  * ```
2239
2618
  */
2240
- const lookup = (key) => (data) => Object.hasOwn(data, key) ? {
2619
+ const lookup = (key) => (record) => Object.hasOwn(record, key) ? {
2241
2620
  kind: "Some",
2242
- value: data[key]
2621
+ value: record[key]
2243
2622
  } : { kind: "None" };
2244
2623
  /**
2245
2624
  * Returns all keys of a record.
2246
2625
  *
2626
+ * @see {@link values} for extracting record values.
2627
+ * @see {@link entries} for extracting key-value pairs.
2628
+ *
2247
2629
  * @example
2248
2630
  * ```ts
2249
2631
  * Rec.keys({ a: 1, b: 2 }); // ["a", "b"]
2250
2632
  * ```
2251
2633
  */
2252
- const keys = (data) => Object.keys(data);
2634
+ const keys = (record) => Object.keys(record);
2253
2635
  /**
2254
2636
  * Returns all values of a record.
2255
2637
  *
2638
+ * @see {@link keys} for extracting record keys.
2639
+ * @see {@link entries} for extracting key-value pairs.
2640
+ *
2256
2641
  * @example
2257
2642
  * ```ts
2258
2643
  * Rec.values({ a: 1, b: 2 }); // [1, 2]
2259
2644
  * ```
2260
2645
  */
2261
- const values = (data) => Object.values(data);
2646
+ const values = (record) => Object.values(record);
2262
2647
  /**
2263
2648
  * Returns all key-value pairs of a record.
2264
2649
  *
2650
+ * @see {@link keys} for extracting record keys.
2651
+ * @see {@link values} for extracting record values.
2652
+ *
2265
2653
  * @example
2266
2654
  * ```ts
2267
2655
  * Rec.entries({ a: 1, b: 2 }); // [["a", 1], ["b", 2]]
2268
2656
  * ```
2269
2657
  */
2270
- const entries = (data) => Object.entries(data);
2658
+ const entries = (record) => Object.entries(record);
2271
2659
  const RecFrom = {
2272
2660
  /**
2273
2661
  * Creates a record from key-value pairs.
@@ -2277,9 +2665,9 @@ const RecFrom = {
2277
2665
  * Rec.from.entries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
2278
2666
  * ```
2279
2667
  */
2280
- entries: (data) => Object.fromEntries(data) };
2668
+ entries: (pairs) => Object.fromEntries(pairs) };
2281
2669
  /**
2282
- * Groups elements of an array into a record keyed by the result of `keyFn`. Each key maps to
2670
+ * Groups elements of an array into a record keyed by the result of `keySelector`. Each key maps to
2283
2671
  * the array of elements that produced it, in insertion order.
2284
2672
  *
2285
2673
  * Unlike `Dict.groupBy`, keys are always strings. Use `Dict.groupBy` when you need non-string
@@ -2293,10 +2681,10 @@ entries: (data) => Object.fromEntries(data) };
2293
2681
  * ); // { a: ["apple", "avocado"], b: ["banana", "blueberry"] }
2294
2682
  * ```
2295
2683
  */
2296
- const groupBy = (keyFn) => (items) => {
2684
+ const groupBy = (keySelector) => (items) => {
2297
2685
  const result = {};
2298
2686
  for (const item of items) {
2299
- const key = keyFn(item);
2687
+ const key = keySelector(item);
2300
2688
  if (Object.hasOwn(result, key)) result[key].push(item);
2301
2689
  else _setKey(result, key, [item]);
2302
2690
  }
@@ -2305,40 +2693,46 @@ const groupBy = (keyFn) => (items) => {
2305
2693
  /**
2306
2694
  * Picks specific keys from a record.
2307
2695
  *
2696
+ * @see {@link omit} for removing specific keys from a record.
2697
+ *
2308
2698
  * @example
2309
2699
  * ```ts
2310
2700
  * pipe({ a: 1, b: 2, c: 3 }, Rec.pick("a", "c")); // { a: 1, c: 3 }
2311
2701
  * ```
2312
2702
  */
2313
- const pick = (...pickedKeys) => (data) => {
2703
+ const pick = (...pickedKeys) => (record) => {
2314
2704
  const result = {};
2315
- for (const key of pickedKeys) if (Object.hasOwn(data, key)) _setKey(result, key, data[key]);
2705
+ for (const key of pickedKeys) if (Object.hasOwn(record, key)) _setKey(result, key, record[key]);
2316
2706
  return result;
2317
2707
  };
2318
2708
  /**
2319
2709
  * Omits specific keys from a record.
2320
2710
  *
2711
+ * @see {@link pick} for retaining only specific keys from a record.
2712
+ *
2321
2713
  * @example
2322
2714
  * ```ts
2323
2715
  * pipe({ a: 1, b: 2, c: 3 }, Rec.omit("b")); // { a: 1, c: 3 }
2324
2716
  * ```
2325
2717
  */
2326
- const omit = (...omittedKeys) => (data) => {
2718
+ const omit = (...omittedKeys) => (record) => {
2327
2719
  const omitSet = new Set(omittedKeys);
2328
2720
  const result = {};
2329
- for (const key of Object.keys(data)) if (!omitSet.has(key)) _setKey(result, key, data[key]);
2721
+ for (const key of Object.keys(record)) if (!omitSet.has(key)) _setKey(result, key, record[key]);
2330
2722
  return result;
2331
2723
  };
2332
2724
  /**
2333
2725
  * Merges two records. Values from the second record take precedence.
2334
2726
  *
2727
+ * @see {@link mergeWith} for merging records with custom collision resolution.
2728
+ *
2335
2729
  * @example
2336
2730
  * ```ts
2337
2731
  * pipe({ a: 1, b: 2 }, Rec.merge({ b: 3, c: 4 })); // { a: 1, b: 3, c: 4 }
2338
2732
  * ```
2339
2733
  */
2340
- const merge = (other) => (data) => ({
2341
- ...data,
2734
+ const merge = (other) => (record) => ({
2735
+ ...record,
2342
2736
  ...other
2343
2737
  });
2344
2738
  function mergeWith(combine) {
@@ -2368,24 +2762,27 @@ function mergeWith(combine) {
2368
2762
  * Rec.size({ a: 1, b: 2 }); // 2
2369
2763
  * ```
2370
2764
  */
2371
- const size$1 = (data) => Object.keys(data).length;
2765
+ const size$1 = (record) => Object.keys(record).length;
2372
2766
  /**
2373
2767
  * Transforms each key while preserving values.
2374
2768
  * If two keys map to the same new key, the last one wins.
2375
2769
  *
2770
+ * @see {@link map} for transforming values.
2771
+ * @see {@link mapEntries} for transforming keys and values simultaneously.
2772
+ *
2376
2773
  * @example
2377
2774
  * ```ts
2378
2775
  * pipe({ firstName: "Alice", lastName: "Smith" }, Rec.mapKeys(k => k.toUpperCase()));
2379
2776
  * // { FIRSTNAME: "Alice", LASTNAME: "Smith" }
2380
2777
  * ```
2381
2778
  */
2382
- const mapKeys = (f) => (data) => {
2383
- const recKeys = Object.keys(data);
2384
- if (recKeys.length === 0) return data;
2779
+ const mapKeys = (transform) => (record) => {
2780
+ const recKeys = Object.keys(record);
2781
+ if (recKeys.length === 0) return record;
2385
2782
  const result = {};
2386
2783
  for (let i = 0; i < recKeys.length; i++) {
2387
2784
  const k = recKeys[i];
2388
- _setKey(result, f(k), data[k]);
2785
+ _setKey(result, transform(k), record[k]);
2389
2786
  }
2390
2787
  return result;
2391
2788
  };
@@ -2399,13 +2796,13 @@ const mapKeys = (f) => (data) => {
2399
2796
  * // { a: 1, c: 3 }
2400
2797
  * ```
2401
2798
  */
2402
- const compact = (data) => {
2403
- const recKeys = Object.keys(data);
2799
+ const compact = (record) => {
2800
+ const recKeys = Object.keys(record);
2404
2801
  if (recKeys.length === 0) return {};
2405
2802
  const result = {};
2406
2803
  for (let i = 0; i < recKeys.length; i++) {
2407
2804
  const k = recKeys[i];
2408
- const v = data[k];
2805
+ const v = record[k];
2409
2806
  if (v.kind === "Some") _setKey(result, k, v.value);
2410
2807
  }
2411
2808
  return result;
@@ -2413,6 +2810,9 @@ const compact = (data) => {
2413
2810
  /**
2414
2811
  * Transforms key and value pairs simultaneously.
2415
2812
  *
2813
+ * @see {@link map} for transforming values.
2814
+ * @see {@link mapKeys} for transforming keys.
2815
+ *
2416
2816
  * @example
2417
2817
  * ```ts
2418
2818
  * pipe(
@@ -2421,13 +2821,13 @@ const compact = (data) => {
2421
2821
  * ); // { A: 10, B: 20 }
2422
2822
  * ```
2423
2823
  */
2424
- const mapEntries = (f) => (data) => {
2425
- const recKeys = Object.keys(data);
2824
+ const mapEntries = (transform) => (record) => {
2825
+ const recKeys = Object.keys(record);
2426
2826
  if (recKeys.length === 0) return {};
2427
2827
  const result = {};
2428
2828
  for (let i = 0; i < recKeys.length; i++) {
2429
2829
  const k = recKeys[i];
2430
- const [newKey, newVal] = f(k, data[k]);
2830
+ const [newKey, newVal] = transform(k, record[k]);
2431
2831
  _setKey(result, newKey, newVal);
2432
2832
  }
2433
2833
  return result;
@@ -2443,12 +2843,12 @@ const mapEntries = (f) => (data) => {
2443
2843
  * ); // { user: { profile: { age: 31 } } }
2444
2844
  * ```
2445
2845
  */
2446
- const updateIn = (path, f) => (data) => {
2846
+ const updateIn = (path, transform) => (record) => {
2447
2847
  const updateNode = (obj, pathKeys) => {
2448
2848
  const [head, ...tail] = pathKeys;
2449
2849
  if (tail.length === 0) return {
2450
2850
  ...obj,
2451
- [head]: f(obj?.[head])
2851
+ [head]: transform(obj?.[head])
2452
2852
  };
2453
2853
  const child = obj && typeof obj === "object" && head in obj ? obj[head] : {};
2454
2854
  return {
@@ -2456,12 +2856,12 @@ const updateIn = (path, f) => (data) => {
2456
2856
  [head]: updateNode(child, tail)
2457
2857
  };
2458
2858
  };
2459
- return updateNode(data, path);
2859
+ return updateNode(record, path);
2460
2860
  };
2461
2861
  const Rec = {
2462
2862
  is: RecIs,
2463
2863
  from: RecFrom,
2464
- to: { Dict: (data) => new globalThis.Map(Object.entries(data)) },
2864
+ to: { Dict: (record) => new globalThis.Map(Object.entries(record)) },
2465
2865
  map: map$1,
2466
2866
  filterMap: filterMap$1,
2467
2867
  mapWithKey,
@@ -2491,13 +2891,13 @@ const Rec = {
2491
2891
  },
2492
2892
  NonEmpty: {
2493
2893
  singleton: (key, value) => ({ [key]: value }),
2494
- from: { Record: (data) => _isNonEmpty(data) ? Maybe.make.some(data) : Maybe.make.none() },
2495
- keys: (data) => keys(data),
2496
- values: (data) => values(data),
2497
- entries: (data) => entries(data),
2498
- reduce: (f) => (data) => values(data).reduce(f),
2499
- map: (f) => (data) => map$1(f)(data),
2500
- mapWithKey: (f) => (data) => mapWithKey(f)(data)
2894
+ from: { record: (record) => _isNonEmpty(record) ? Maybe.make.some(record) : Maybe.make.none() },
2895
+ keys: (record) => keys(record),
2896
+ values: (record) => values(record),
2897
+ entries: (record) => entries(record),
2898
+ reduce: (reducer) => (record) => values(record).reduce(reducer),
2899
+ map: (transform) => (record) => map$1(transform)(record),
2900
+ mapWithKey: (transform) => (record) => mapWithKey(transform)(record)
2501
2901
  }
2502
2902
  };
2503
2903
  //#endregion
@@ -2508,18 +2908,21 @@ const StrNonEmptyConst = { from: {
2508
2908
  *
2509
2909
  * @example
2510
2910
  * ```ts
2511
- * Str.NonEmpty.from.String("hello"); // Some("hello")
2512
- * Str.NonEmpty.from.String(""); // None
2911
+ * Str.NonEmpty.from.string("hello"); // Some("hello")
2912
+ * Str.NonEmpty.from.string(""); // None
2513
2913
  * ```
2514
2914
  */
2515
- String: (s) => s.length > 0 ? Maybe.make.some(s) : Maybe.make.none() } };
2516
- const isEmpty$1 = (s) => s.length === 0;
2517
- const isNonEmpty$1 = (s) => s.length > 0;
2915
+ string: (text) => text.length > 0 ? Maybe.make.some(text) : Maybe.make.none() } };
2916
+ const isEmpty$1 = (text) => text.length === 0;
2917
+ const isNonEmpty$1 = (text) => text.length > 0;
2918
+ const isBlank = (text) => text.trim().length === 0;
2518
2919
  const Str = {
2519
2920
  is: {
2520
2921
  /**
2521
2922
  * Returns `true` when the string is empty.
2522
2923
  *
2924
+ * @see {@link nonEmpty} for checking if a string contains at least one character.
2925
+ *
2523
2926
  * @example
2524
2927
  * ```ts
2525
2928
  * pipe("", Str.is.empty); // true
@@ -2529,8 +2932,22 @@ const Str = {
2529
2932
  empty: isEmpty$1,
2530
2933
  /**
2531
2934
  * Type guard to check if a string is non-empty.
2935
+ *
2936
+ * @see {@link empty} for checking if a string has zero length.
2532
2937
  */
2533
- nonEmpty: isNonEmpty$1
2938
+ nonEmpty: isNonEmpty$1,
2939
+ /**
2940
+ * Returns `true` when the string is empty or contains only whitespace.
2941
+ *
2942
+ * @see {@link empty} for checking zero length without trimming whitespace.
2943
+ *
2944
+ * @example
2945
+ * ```ts
2946
+ * pipe(" ", Str.is.blank); // true
2947
+ * pipe("hi", Str.is.blank); // false
2948
+ * ```
2949
+ */
2950
+ blank: isBlank
2534
2951
  },
2535
2952
  /**
2536
2953
  * Splits a string by a separator. Data-last: use in `pipe`.
@@ -2540,7 +2957,7 @@ const Str = {
2540
2957
  * pipe("a,b,c", Str.split(",")); // ["a", "b", "c"]
2541
2958
  * ```
2542
2959
  */
2543
- split: (separator) => (s) => s.split(separator),
2960
+ split: (separator) => (text) => text.split(separator),
2544
2961
  /**
2545
2962
  * Removes leading and trailing whitespace from a string.
2546
2963
  *
@@ -2549,7 +2966,7 @@ const Str = {
2549
2966
  * pipe(" hello ", Str.trim); // "hello"
2550
2967
  * ```
2551
2968
  */
2552
- trim: (s) => s.trim(),
2969
+ trim: (text) => text.trim(),
2553
2970
  /**
2554
2971
  * Returns `true` when the string contains the given substring.
2555
2972
  *
@@ -2559,74 +2976,88 @@ const Str = {
2559
2976
  * pipe("hello world", Str.includes("xyz")); // false
2560
2977
  * ```
2561
2978
  */
2562
- includes: (substring) => (s) => s.includes(substring),
2979
+ includes: (substring) => (text) => text.includes(substring),
2563
2980
  /**
2564
2981
  * Replaces the first occurrence of a pattern in a string. Data-last: use in `pipe`.
2565
2982
  *
2983
+ * @see {@link replaceAll} for substituting every occurrence instead of only the first.
2984
+ *
2566
2985
  * @example
2567
2986
  * ```ts
2568
2987
  * pipe("foo foo foo", Str.replace("foo", "bar")); // "bar foo foo"
2569
2988
  * pipe("Hello World", Str.replace(/world/i, "Earth")); // "Hello Earth"
2570
2989
  * ```
2571
2990
  */
2572
- replace: (pattern, replacement) => (s) => s.replace(pattern, replacement),
2991
+ replace: (pattern, replacement) => (text) => text.replace(pattern, replacement),
2573
2992
  /**
2574
2993
  * Replaces all occurrences of a pattern in a string. Data-last: use in `pipe`.
2575
2994
  *
2995
+ * @see {@link replace} for substituting only the first occurrence.
2996
+ *
2576
2997
  * @example
2577
2998
  * ```ts
2578
2999
  * pipe("foo foo foo", Str.replaceAll("foo", "bar")); // "bar bar bar"
2579
3000
  * pipe("aAbBaA", Str.replaceAll(/a/gi, "x")); // "xxBBxx"
2580
3001
  * ```
2581
3002
  */
2582
- replaceAll: (pattern, replacement) => (s) => s.replaceAll(pattern, replacement),
3003
+ replaceAll: (pattern, replacement) => (text) => text.replaceAll(pattern, replacement),
2583
3004
  /**
2584
3005
  * Returns `true` when the string starts with the given prefix.
2585
3006
  *
3007
+ * @see {@link endsWith} for checking suffix matches.
3008
+ *
2586
3009
  * @example
2587
3010
  * ```ts
2588
3011
  * pipe("hello world", Str.startsWith("hello")); // true
2589
3012
  * pipe("hello world", Str.startsWith("world")); // false
2590
3013
  * ```
2591
3014
  */
2592
- startsWith: (prefix) => (s) => s.startsWith(prefix),
3015
+ startsWith: (prefix) => (text) => text.startsWith(prefix),
2593
3016
  /**
2594
3017
  * Returns `true` when the string ends with the given suffix.
2595
3018
  *
3019
+ * @see {@link startsWith} for checking prefix matches.
3020
+ *
2596
3021
  * @example
2597
3022
  * ```ts
2598
3023
  * pipe("hello world", Str.endsWith("world")); // true
2599
3024
  * pipe("hello world", Str.endsWith("hello")); // false
2600
3025
  * ```
2601
3026
  */
2602
- endsWith: (suffix) => (s) => s.endsWith(suffix),
3027
+ endsWith: (suffix) => (text) => text.endsWith(suffix),
2603
3028
  /**
2604
3029
  * Converts a string to uppercase.
2605
3030
  *
3031
+ * @see {@link toLowerCase} for lowercasing characters.
3032
+ *
2606
3033
  * @example
2607
3034
  * ```ts
2608
3035
  * pipe("hello", Str.toUpperCase); // "HELLO"
2609
3036
  * ```
2610
3037
  */
2611
- toUpperCase: (s) => s.toUpperCase(),
3038
+ toUpperCase: (text) => text.toUpperCase(),
2612
3039
  /**
2613
3040
  * Converts a string to lowercase.
2614
3041
  *
3042
+ * @see {@link toUpperCase} for uppercasing characters.
3043
+ *
2615
3044
  * @example
2616
3045
  * ```ts
2617
3046
  * pipe("HELLO", Str.toLowerCase); // "hello"
2618
3047
  * ```
2619
3048
  */
2620
- toLowerCase: (s) => s.toLowerCase(),
3049
+ toLowerCase: (text) => text.toLowerCase(),
2621
3050
  /**
2622
3051
  * Converts the first character of a string to uppercase.
2623
3052
  *
3053
+ * @see {@link uncapitalize} for converting the first character to lowercase.
3054
+ *
2624
3055
  * @example
2625
3056
  * ```ts
2626
3057
  * pipe("hello", Str.capitalize); // "Hello"
2627
3058
  * ```
2628
3059
  */
2629
- capitalize: (s) => s.length === 0 ? "" : s.charAt(0).toUpperCase() + s.slice(1),
3060
+ capitalize: (text) => text.length === 0 ? "" : text.charAt(0).toUpperCase() + text.slice(1),
2630
3061
  /**
2631
3062
  * Splits a string into lines, normalising `\r\n` and `\r` line endings.
2632
3063
  *
@@ -2636,7 +3067,7 @@ const Str = {
2636
3067
  * Str.lines("a\r\nb"); // ["a", "b"]
2637
3068
  * ```
2638
3069
  */
2639
- lines: (s) => s.split(/\r?\n|\r/),
3070
+ lines: (text) => text.split(/\r?\n|\r/),
2640
3071
  /**
2641
3072
  * Splits a string into words on any whitespace boundary, filtering out empty strings.
2642
3073
  *
@@ -2645,17 +3076,7 @@ const Str = {
2645
3076
  * Str.words(" hello world "); // ["hello", "world"]
2646
3077
  * ```
2647
3078
  */
2648
- words: (s) => s.trim().split(/\s+/).filter(Boolean),
2649
- /**
2650
- * Returns `true` when the string is empty or contains only whitespace.
2651
- *
2652
- * @example
2653
- * ```ts
2654
- * pipe(" ", Str.isBlank); // true
2655
- * pipe("hi", Str.isBlank); // false
2656
- * ```
2657
- */
2658
- isBlank: (s) => s.trim().length === 0,
3079
+ words: (text) => text.trim().split(/\s+/).filter(Boolean),
2659
3080
  /**
2660
3081
  * Returns the length of the string.
2661
3082
  *
@@ -2665,7 +3086,7 @@ const Str = {
2665
3086
  * pipe("", Str.length); // 0
2666
3087
  * ```
2667
3088
  */
2668
- length: (s) => s.length,
3089
+ length: (text) => text.length,
2669
3090
  /**
2670
3091
  * Extracts a substring between two indices. Data-last: use in `pipe`.
2671
3092
  *
@@ -2675,27 +3096,31 @@ const Str = {
2675
3096
  * pipe("hello", Str.slice(2)); // "llo"
2676
3097
  * ```
2677
3098
  */
2678
- slice: (start, end) => (s) => s.slice(start, end),
3099
+ slice: (start, end) => (text) => text.slice(start, end),
2679
3100
  /**
2680
3101
  * Pads the start of a string to a specified length. Data-last: use in `pipe`.
2681
3102
  *
3103
+ * @see {@link padEnd} for padding the right side of a string.
3104
+ *
2682
3105
  * @example
2683
3106
  * ```ts
2684
3107
  * pipe("5", Str.padStart(3, "0")); // "005"
2685
3108
  * pipe("hi", Str.padStart(5)); // " hi"
2686
3109
  * ```
2687
3110
  */
2688
- padStart: (maxLength, fillString) => (s) => s.padStart(maxLength, fillString),
3111
+ padStart: (maxLength, fillString) => (text) => text.padStart(maxLength, fillString),
2689
3112
  /**
2690
3113
  * Pads the end of a string to a specified length. Data-last: use in `pipe`.
2691
3114
  *
3115
+ * @see {@link padStart} for padding the left side of a string.
3116
+ *
2692
3117
  * @example
2693
3118
  * ```ts
2694
3119
  * pipe("hi", Str.padEnd(5, ".")); // "hi..."
2695
3120
  * pipe("hi", Str.padEnd(5)); // "hi "
2696
3121
  * ```
2697
3122
  */
2698
- padEnd: (maxLength, fillString) => (s) => s.padEnd(maxLength, fillString),
3123
+ padEnd: (maxLength, fillString) => (text) => text.padEnd(maxLength, fillString),
2699
3124
  /**
2700
3125
  * Safe number parsers that return `Maybe` instead of `NaN`.
2701
3126
  */
@@ -2703,6 +3128,8 @@ const Str = {
2703
3128
  /**
2704
3129
  * Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
2705
3130
  *
3131
+ * @see {@link float} for parsing floating-point numbers.
3132
+ *
2706
3133
  * @example
2707
3134
  * ```ts
2708
3135
  * Str.parse.int("42"); // Some(42)
@@ -2710,14 +3137,16 @@ const Str = {
2710
3137
  * Str.parse.int("abc"); // None
2711
3138
  * ```
2712
3139
  */
2713
- int: (s) => {
2714
- if (s.length === 0) return Maybe.make.none();
2715
- const n = Number.parseInt(s, 10);
3140
+ int: (text) => {
3141
+ if (text.length === 0) return Maybe.make.none();
3142
+ const n = Number.parseInt(text, 10);
2716
3143
  return Number.isNaN(n) ? Maybe.make.none() : Maybe.make.some(n);
2717
3144
  },
2718
3145
  /**
2719
3146
  * Parses a string as a floating-point number. Returns `None` if the result is `NaN`.
2720
3147
  *
3148
+ * @see {@link int} for parsing base-10 integers.
3149
+ *
2721
3150
  * @example
2722
3151
  * ```ts
2723
3152
  * Str.parse.float("3.14"); // Some(3.14)
@@ -2725,38 +3154,57 @@ const Str = {
2725
3154
  * Str.parse.float("abc"); // None
2726
3155
  * ```
2727
3156
  */
2728
- float: (s) => {
2729
- if (s.length === 0) return Maybe.make.none();
2730
- const n = Number.parseFloat(s);
3157
+ float: (text) => {
3158
+ if (text.length === 0) return Maybe.make.none();
3159
+ const n = Number.parseFloat(text);
2731
3160
  return Number.isNaN(n) ? Maybe.make.none() : Maybe.make.some(n);
2732
3161
  }
2733
3162
  },
2734
3163
  /**
2735
- * Safely parses a JSON string, returning a `Result<SyntaxError, unknown>`.
3164
+ * Matches a string against a regular expression.
3165
+ * Pure and safe: resets `pattern.lastIndex = 0` to prevent bugs with stateful `/g` and `/y` regexes.
3166
+ *
3167
+ * @see {@link test} for boolean validation without extracting capture groups.
2736
3168
  *
2737
3169
  * @example
2738
3170
  * ```ts
2739
- * Str.parseJson('{"a": 1}'); // Ok({ a: 1 })
2740
- * Str.parseJson('invalid'); // Err(SyntaxError)
3171
+ * pipe("hello 42", Str.match(/\d+/)); // Some(["42"])
3172
+ * pipe("hello", Str.match(/\d+/)); // None
2741
3173
  * ```
2742
3174
  */
2743
- parseJson: (s) => {
2744
- try {
2745
- return Result.make.ok(JSON.parse(s));
2746
- } catch (error) {
2747
- return Result.make.err(error);
2748
- }
3175
+ match: (pattern) => (text) => {
3176
+ pattern.lastIndex = 0;
3177
+ const result = text.match(pattern);
3178
+ return result !== null ? Maybe.make.some(result) : Maybe.make.none();
3179
+ },
3180
+ /**
3181
+ * Tests whether a string matches a regular expression.
3182
+ * Pure and safe: resets `pattern.lastIndex = 0` to prevent bugs with stateful `/g` and `/y` regexes.
3183
+ *
3184
+ * @see {@link match} for extracting capture groups into a Maybe.
3185
+ *
3186
+ * @example
3187
+ * ```ts
3188
+ * pipe("user@example.com", Str.test(/^[^@]+@[^@]+$/)); // true
3189
+ * pipe("invalid-email", Str.test(/^[^@]+@[^@]+$/)); // false
3190
+ * ```
3191
+ */
3192
+ test: (pattern) => (text) => {
3193
+ pattern.lastIndex = 0;
3194
+ return pattern.test(text);
2749
3195
  },
2750
3196
  /**
2751
3197
  * Converts the first character of a string to lower case.
2752
3198
  *
3199
+ * @see {@link capitalize} for converting the first character to uppercase.
3200
+ *
2753
3201
  * @example
2754
3202
  * ```ts
2755
- * Str.uncapitalize("Hello"); // "hello"
2756
- * Str.uncapitalize(""); // ""
3203
+ * pipe("Hello", Str.uncapitalize); // "hello"
3204
+ * pipe("", Str.uncapitalize); // ""
2757
3205
  * ```
2758
3206
  */
2759
- uncapitalize: (s) => s.length === 0 ? "" : s.charAt(0).toLowerCase() + s.slice(1),
3207
+ uncapitalize: (text) => text.length === 0 ? "" : text.charAt(0).toLowerCase() + text.slice(1),
2760
3208
  /**
2761
3209
  * Truncates a string to a maximum length, appending an optional suffix (default `"..."`).
2762
3210
  * Data-last curried signature.
@@ -2768,100 +3216,158 @@ const Str = {
2768
3216
  * pipe("Hello, world!", Str.truncate({ length: 8, suffix: "…" })); // "Hello, w…"
2769
3217
  * ```
2770
3218
  */
2771
- truncate: (options) => (s) => {
3219
+ truncate: (options) => (text) => {
2772
3220
  const { length: targetLength, suffix = "..." } = options;
2773
- if (s.length <= targetLength) return s;
3221
+ if (text.length <= targetLength) return text;
2774
3222
  if (targetLength <= suffix.length) return suffix.slice(0, targetLength);
2775
- return s.slice(0, targetLength - suffix.length) + suffix;
3223
+ return text.slice(0, targetLength - suffix.length) + suffix;
2776
3224
  },
2777
3225
  NonEmpty: StrNonEmptyConst
2778
3226
  };
2779
3227
  //#endregion
2780
3228
  //#region src/Data/Uniq.ts
2781
- const isEmpty = (s) => s.size === 0;
2782
- const isNonEmpty = (s) => s.size > 0;
3229
+ const isEmpty = (set) => set.size === 0;
3230
+ const isNonEmpty = (set) => set.size > 0;
2783
3231
  const empty = () => new globalThis.Set();
2784
3232
  const singleton = (item) => new globalThis.Set([item]);
2785
- const fromArray = (arr) => new globalThis.Set(arr);
2786
- const has = (item) => (s) => s.has(item);
2787
- const size = (s) => s.size;
2788
- const add = (item) => (s) => {
2789
- if (s.has(item)) return s;
2790
- const result = new globalThis.Set(s);
3233
+ const fromArray = (items) => new globalThis.Set(items);
3234
+ /**
3235
+ * Returns `true` when the set contains the given element.
3236
+ *
3237
+ * @see {@link add} for inserting an element into a set.
3238
+ * @see {@link remove} for deleting an element from a set.
3239
+ */
3240
+ const has = (item) => (set) => set.has(item);
3241
+ const size = (set) => set.size;
3242
+ /**
3243
+ * Returns a new set with the element added.
3244
+ *
3245
+ * @see {@link remove} for deleting an element from a set.
3246
+ * @see {@link toggle} for toggling presence of an element.
3247
+ */
3248
+ const add = (item) => (set) => {
3249
+ if (set.has(item)) return set;
3250
+ const result = new globalThis.Set(set);
2791
3251
  result.add(item);
2792
3252
  return result;
2793
3253
  };
2794
- const remove = (item) => (s) => {
2795
- if (!s.has(item)) return s;
2796
- const result = new globalThis.Set(s);
3254
+ /**
3255
+ * Returns a new set with the element removed.
3256
+ *
3257
+ * @see {@link add} for adding an element to a set.
3258
+ */
3259
+ const remove = (item) => (set) => {
3260
+ if (!set.has(item)) return set;
3261
+ const result = new globalThis.Set(set);
2797
3262
  result.delete(item);
2798
3263
  return result;
2799
3264
  };
2800
- const toggle = (item) => (s) => {
2801
- const result = new globalThis.Set(s);
3265
+ /**
3266
+ * Toggles presence of an element in a set.
3267
+ *
3268
+ * @see {@link add} for unconditionally adding an element.
3269
+ * @see {@link remove} for unconditionally removing an element.
3270
+ */
3271
+ const toggle = (item) => (set) => {
3272
+ const result = new globalThis.Set(set);
2802
3273
  if (result.has(item)) result.delete(item);
2803
3274
  else result.add(item);
2804
3275
  return result;
2805
3276
  };
2806
- const map = (f) => (s) => {
3277
+ /**
3278
+ * Transforms each element of a set into a new set.
3279
+ *
3280
+ * @see {@link filterMap} for mapping and filtering in a single step.
3281
+ */
3282
+ const map = (transform) => (set) => {
2807
3283
  const result = new globalThis.Set();
2808
- for (const item of s) result.add(f(item));
3284
+ for (const item of set) result.add(transform(item));
2809
3285
  return result;
2810
3286
  };
2811
- const filter = (predicate) => (s) => {
3287
+ /**
3288
+ * Filters elements of a set by a predicate.
3289
+ *
3290
+ * @see {@link filterMap} for filtering and mapping simultaneously.
3291
+ */
3292
+ const filter = (predicate) => (set) => {
2812
3293
  const result = new globalThis.Set();
2813
- for (const item of s) if (predicate(item)) result.add(item);
3294
+ for (const item of set) if (predicate(item)) result.add(item);
2814
3295
  return result;
2815
3296
  };
2816
- const filterMap = (f) => (s) => {
3297
+ /**
3298
+ * Transforms elements with a function returning `Maybe`, keeping only `Some` values.
3299
+ *
3300
+ * @see {@link filter} for filtering with a boolean predicate.
3301
+ * @see {@link map} for transforming without filtering.
3302
+ */
3303
+ const filterMap = (transform) => (set) => {
2817
3304
  const result = new globalThis.Set();
2818
- for (const item of s) {
2819
- const mb = f(item);
3305
+ for (const item of set) {
3306
+ const mb = transform(item);
2820
3307
  if (mb.kind === "Some") result.add(mb.value);
2821
3308
  }
2822
3309
  return result;
2823
3310
  };
2824
- const union = (other) => (s) => {
2825
- const set = s;
2826
- if (typeof set.union === "function") return set.union(other);
2827
- const result = new globalThis.Set(s);
3311
+ /**
3312
+ * Computes the union of two sets.
3313
+ *
3314
+ * @see {@link intersection} for keeping only elements present in both sets.
3315
+ * @see {@link difference} for subtracting elements.
3316
+ */
3317
+ const union = (other) => (set) => {
3318
+ const s = set;
3319
+ if (typeof s.union === "function") return s.union(other);
3320
+ const result = new globalThis.Set(set);
2828
3321
  for (const item of other) result.add(item);
2829
3322
  return result;
2830
3323
  };
2831
- const intersection = (other) => (s) => {
2832
- const set = s;
2833
- if (typeof set.intersection === "function") return set.intersection(other);
3324
+ /**
3325
+ * Computes the intersection of two sets.
3326
+ *
3327
+ * @see {@link union} for combining elements from both sets.
3328
+ * @see {@link difference} for subtracting elements.
3329
+ */
3330
+ const intersection = (other) => (set) => {
3331
+ const s = set;
3332
+ if (typeof s.intersection === "function") return s.intersection(other);
2834
3333
  const result = new globalThis.Set();
2835
- for (const item of s) if (other.has(item)) result.add(item);
3334
+ for (const item of set) if (other.has(item)) result.add(item);
2836
3335
  return result;
2837
3336
  };
2838
- const difference = (other) => (s) => {
2839
- const set = s;
2840
- if (typeof set.difference === "function") return set.difference(other);
3337
+ /**
3338
+ * Computes the set difference (`set \ other`).
3339
+ *
3340
+ * @see {@link union} for combining all elements.
3341
+ * @see {@link intersection} for keeping only common elements.
3342
+ */
3343
+ const difference = (other) => (set) => {
3344
+ const s = set;
3345
+ if (typeof s.difference === "function") return s.difference(other);
2841
3346
  const result = new globalThis.Set();
2842
- for (const item of s) if (!other.has(item)) result.add(item);
3347
+ for (const item of set) if (!other.has(item)) result.add(item);
2843
3348
  return result;
2844
3349
  };
2845
- const isSubsetOf = (other) => (s) => {
2846
- const set = s;
2847
- if (typeof set.isSubsetOf === "function") return set.isSubsetOf(other);
2848
- for (const item of s) if (!other.has(item)) return false;
3350
+ const isSubsetOf = (other) => (set) => {
3351
+ const s = set;
3352
+ if (typeof s.isSubsetOf === "function") return s.isSubsetOf(other);
3353
+ for (const item of set) if (!other.has(item)) return false;
2849
3354
  return true;
2850
3355
  };
2851
- const reduce = (init, f) => (s) => {
2852
- let acc = init;
2853
- for (const item of s) acc = f(acc, item);
3356
+ const reduce = (initial, reducer) => (set) => {
3357
+ let acc = initial;
3358
+ for (const item of set) acc = reducer(acc, item);
2854
3359
  return acc;
2855
3360
  };
2856
- const toArray = (s) => [...s];
3361
+ const toArray = (set) => [...set];
2857
3362
  const Uniq = {
2858
3363
  is: {
2859
3364
  empty: isEmpty,
2860
- nonEmpty: isNonEmpty
3365
+ nonEmpty: isNonEmpty,
3366
+ subsetOf: isSubsetOf
2861
3367
  },
2862
3368
  empty,
2863
3369
  singleton,
2864
- from: { Array: fromArray },
3370
+ from: { array: fromArray },
2865
3371
  has,
2866
3372
  size,
2867
3373
  add,
@@ -2874,15 +3380,14 @@ const Uniq = {
2874
3380
  union,
2875
3381
  intersection,
2876
3382
  difference,
2877
- isSubsetOf,
2878
3383
  reduce,
2879
- to: { Array: toArray },
3384
+ to: { array: toArray },
2880
3385
  NonEmpty: {
2881
3386
  singleton: (item) => new globalThis.Set([item]),
2882
- from: { Set: (s) => s.size > 0 ? Maybe.make.some(s) : Maybe.make.none() },
2883
- reduce: (f) => (s) => toArray(s).reduce(f),
2884
- map: (f) => (s) => map(f)(s),
2885
- to: { Array: (s) => toArray(s) }
3387
+ from: { set: (set) => set.size > 0 ? Maybe.make.some(set) : Maybe.make.none() },
3388
+ reduce: (reducer) => (set) => toArray(set).reduce(reducer),
3389
+ map: (transform) => (set) => map(transform)(set),
3390
+ to: { array: (set) => toArray(set) }
2886
3391
  }
2887
3392
  };
2888
3393
  //#endregion