effect 3.14.2 → 3.14.3

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/src/HashSet.ts CHANGED
@@ -1,4 +1,254 @@
1
1
  /**
2
+ * # HashSet
3
+ *
4
+ * An immutable `HashSet` provides a collection of unique values with efficient
5
+ * lookup, insertion and removal. Once created, a `HashSet` cannot be modified;
6
+ * any operation that would alter the set instead returns a new `HashSet` with
7
+ * the changes. This immutability offers benefits like predictable state
8
+ * management and easier reasoning about your code.
9
+ *
10
+ * ## What Problem Does It Solve?
11
+ *
12
+ * `HashSet` solves the problem of maintaining an unsorted collection where each
13
+ * value appears exactly once, with fast operations for checking membership and
14
+ * adding/removing values.
15
+ *
16
+ * ## When to Use
17
+ *
18
+ * Use `HashSet` when you need:
19
+ *
20
+ * - A collection with no duplicate values
21
+ * - Efficient membership testing (**`O(1)`** average complexity)
22
+ * - Set operations like union, intersection, and difference
23
+ * - An immutable data structure that preserves functional programming patterns
24
+ *
25
+ * ## Advanced Features
26
+ *
27
+ * HashSet provides operations for:
28
+ *
29
+ * - Transforming sets with map and flatMap
30
+ * - Filtering elements with filter
31
+ * - Combining sets with union, intersection and difference
32
+ * - Performance optimizations via mutable operations in controlled contexts
33
+ *
34
+ * ## Performance Characteristics
35
+ *
36
+ * - **Lookup** operations ({@linkcode HashSet.has}): **`O(1)`** average time
37
+ * complexity
38
+ * - **Insertion** operations ({@linkcode HashSet.add}): **`O(1)`** average time
39
+ * complexity
40
+ * - **Removal** operations ({@linkcode HashSet.remove}): **`O(1)`** average time
41
+ * complexity
42
+ * - **Set** operations ({@linkcode HashSet.union},
43
+ * {@linkcode HashSet.intersection}): **`O(n)`** where n is the size of the
44
+ * smaller set
45
+ * - **Iteration**: **`O(n)`** where n is the size of the set
46
+ *
47
+ * The HashSet data structure implements the following traits:
48
+ *
49
+ * - {@link Iterable}: allows iterating over the values in the set
50
+ * - {@link Equal}: allows comparing two sets for value-based equality
51
+ * - {@link Pipeable}: allows chaining operations with the pipe operator
52
+ * - {@link Inspectable}: allows inspecting the contents of the set
53
+ *
54
+ * ## Operations Reference
55
+ *
56
+ * | Category | Operation | Description | Complexity |
57
+ * | ------------ | -------------------------------- | ------------------------------------------- | ---------- |
58
+ * | constructors | {@linkcode HashSet.empty} | Creates an empty HashSet | O(1) |
59
+ * | constructors | {@linkcode HashSet.fromIterable} | Creates a HashSet from an iterable | O(n) |
60
+ * | constructors | {@linkcode HashSet.make} | Creates a HashSet from multiple values | O(n) |
61
+ * | | | | |
62
+ * | elements | {@linkcode HashSet.has} | Checks if a value exists in the set | O(1) avg |
63
+ * | elements | {@linkcode HashSet.some} | Checks if any element satisfies a predicate | O(n) |
64
+ * | elements | {@linkcode HashSet.every} | Checks if all elements satisfy a predicate | O(n) |
65
+ * | elements | {@linkcode HashSet.isSubset} | Checks if a set is a subset of another | O(n) |
66
+ * | | | | |
67
+ * | getters | {@linkcode HashSet.values} | Gets an iterator of all values | O(1) |
68
+ * | getters | {@linkcode HashSet.toValues} | Gets an array of all values | O(n) |
69
+ * | getters | {@linkcode HashSet.size} | Gets the number of elements | O(1) |
70
+ * | | | | |
71
+ * | mutations | {@linkcode HashSet.add} | Adds a value to the set | O(1) avg |
72
+ * | mutations | {@linkcode HashSet.remove} | Removes a value from the set | O(1) avg |
73
+ * | mutations | {@linkcode HashSet.toggle} | Toggles a value's presence | O(1) avg |
74
+ * | | | | |
75
+ * | operations | {@linkcode HashSet.difference} | Computes set difference (A - B) | O(n) |
76
+ * | operations | {@linkcode HashSet.intersection} | Computes set intersection (A ∩ B) | O(n) |
77
+ * | operations | {@linkcode HashSet.union} | Computes set union (A ∪ B) | O(n) |
78
+ * | | | | |
79
+ * | mapping | {@linkcode HashSet.map} | Transforms each element | O(n) |
80
+ * | | | | |
81
+ * | sequencing | {@linkcode HashSet.flatMap} | Transforms and flattens elements | O(n) |
82
+ * | | | | |
83
+ * | traversing | {@linkcode HashSet.forEach} | Applies a function to each element | O(n) |
84
+ * | | | | |
85
+ * | folding | {@linkcode HashSet.reduce} | Reduces the set to a single value | O(n) |
86
+ * | | | | |
87
+ * | filtering | {@linkcode HashSet.filter} | Keeps elements that satisfy a predicate | O(n) |
88
+ * | | | | |
89
+ * | partitioning | {@linkcode HashSet.partition} | Splits into two sets by a predicate | O(n) |
90
+ *
91
+ * ## Notes
92
+ *
93
+ * ### Composability with the Effect Ecosystem:
94
+ *
95
+ * This `HashSet` is designed to work seamlessly within the Effect ecosystem. It
96
+ * implements the {@link Iterable}, {@link Equal}, {@link Pipeable}, and
97
+ * {@link Inspectable} traits from Effect. This ensures compatibility with other
98
+ * Effect data structures and functionalities. For example, you can easily use
99
+ * Effect's `pipe` method to chain operations on the `HashSet`.
100
+ *
101
+ * **Equality of Elements with Effect's {@link Equal `Equal`} Trait:**
102
+ *
103
+ * This `HashSet` relies on Effect's {@link Equal} trait to determine the
104
+ * uniqueness of elements within the set. The way equality is checked depends on
105
+ * the type of the elements:
106
+ *
107
+ * - **Primitive Values:** For primitive JavaScript values like strings, numbers,
108
+ * booleans, `null`, and `undefined`, equality is determined by their value
109
+ * (similar to the `===` operator).
110
+ * - **Objects and Custom Types:** For objects and other custom types, equality is
111
+ * determined by whether those types implement the {@link Equal} interface
112
+ * themselves. If an element type implements `Equal`, the `HashSet` will
113
+ * delegate to that implementation to perform the equality check. This allows
114
+ * you to define custom logic for determining when two instances of your
115
+ * objects should be considered equal based on their properties, rather than
116
+ * just their object identity.
117
+ *
118
+ * ```ts
119
+ * import { Equal, Hash, HashSet } from "effect"
120
+ *
121
+ * class Person implements Equal.Equal {
122
+ * constructor(
123
+ * readonly id: number, // Unique identifier
124
+ * readonly name: string,
125
+ * readonly age: number
126
+ * ) {}
127
+ *
128
+ * // Define equality based on id, name, and age
129
+ * [Equal.symbol](that: Equal.Equal): boolean {
130
+ * if (that instanceof Person) {
131
+ * return (
132
+ * Equal.equals(this.id, that.id) &&
133
+ * Equal.equals(this.name, that.name) &&
134
+ * Equal.equals(this.age, that.age)
135
+ * )
136
+ * }
137
+ * return false
138
+ * }
139
+ *
140
+ * // Generate a hash code based on the unique id
141
+ * [Hash.symbol](): number {
142
+ * return Hash.hash(this.id)
143
+ * }
144
+ * }
145
+ *
146
+ * // Creating a HashSet with objects that implement the Equal interface
147
+ * const set = HashSet.empty().pipe(
148
+ * HashSet.add(new Person(1, "Alice", 30)),
149
+ * HashSet.add(new Person(1, "Alice", 30))
150
+ * )
151
+ *
152
+ * // HashSet recognizes them as equal, so only one element is stored
153
+ * console.log(HashSet.size(set))
154
+ * // Output: 1
155
+ * ```
156
+ *
157
+ * **Simplifying Equality and Hashing with `Data` and `Schema`:**
158
+ *
159
+ * Effect's {@link Data} and {@link Schema `Schema.Data`} modules offer powerful
160
+ * ways to automatically handle the implementation of both the {@link Equal} and
161
+ * {@link Hash} traits for your custom data structures.
162
+ *
163
+ * - **`Data` Module:** By using constructors like `Data.struct`, `Data.tuple`,
164
+ * `Data.array`, or `Data.case` to define your data types, Effect
165
+ * automatically generates the necessary implementations for value-based
166
+ * equality and consistent hashing. This significantly reduces boilerplate and
167
+ * ensures correctness.
168
+ *
169
+ * ```ts
170
+ * import { HashSet, Data, Equal } from "effect"
171
+ * import assert from "node:assert/strict"
172
+ *
173
+ * // Data.* implements the `Equal` traits for us
174
+ * const person1 = Data.struct({ id: 1, name: "Alice", age: 30 })
175
+ * const person2 = Data.struct({ id: 1, name: "Alice", age: 30 })
176
+ *
177
+ * assert(Equal.equals(person1, person2))
178
+ *
179
+ * const set = HashSet.empty().pipe(
180
+ * HashSet.add(person1),
181
+ * HashSet.add(person2)
182
+ * )
183
+ *
184
+ * // HashSet recognizes them as equal, so only one element is stored
185
+ * console.log(HashSet.size(set)) // Output: 1
186
+ * ```
187
+ *
188
+ * - **`Schema` Module:** When defining data schemas using the {@link Schema}
189
+ * module, you can use `Schema.Data` to automatically include the `Equal` and
190
+ * `Hash` traits in the decoded objects. This is particularly important when
191
+ * working with `HashSet`. **For decoded objects to be correctly recognized as
192
+ * equal within a `HashSet`, ensure that the schema for those objects is
193
+ * defined using `Schema.Data`.**
194
+ *
195
+ * ```ts
196
+ * import { Equal, HashSet, Schema } from "effect"
197
+ * import assert from "node:assert/strict"
198
+ *
199
+ * // Schema.Data implements the `Equal` traits for us
200
+ * const PersonSchema = Schema.Data(
201
+ * Schema.Struct({
202
+ * id: Schema.Number,
203
+ * name: Schema.String,
204
+ * age: Schema.Number
205
+ * })
206
+ * )
207
+ *
208
+ * const Person = Schema.decode(PersonSchema)
209
+ *
210
+ * const person1 = Person({ id: 1, name: "Alice", age: 30 })
211
+ * const person2 = Person({ id: 1, name: "Alice", age: 30 })
212
+ *
213
+ * assert(Equal.equals(person1, person2)) // Output: true
214
+ *
215
+ * const set = HashSet.empty().pipe(
216
+ * HashSet.add(person1),
217
+ * HashSet.add(person2)
218
+ * )
219
+ *
220
+ * // HashSet thanks to Schema.Data implementation of the `Equal` trait, recognizes the two Person as equal, so only one element is stored
221
+ * console.log(HashSet.size(set)) // Output: 1
222
+ * ```
223
+ *
224
+ * ### Interoperability with the JavaScript Runtime:
225
+ *
226
+ * To interoperate with the regular JavaScript runtime, Effect's `HashSet`
227
+ * provides methods to access its elements in formats readily usable by
228
+ * JavaScript APIs: {@link values `HashSet.values`},
229
+ * {@link toValues `HashSet.toValues`}
230
+ *
231
+ * ```ts
232
+ * import { HashSet } from "effect"
233
+ *
234
+ * const hashSet: HashSet.HashSet<number> = HashSet.make(1, 2, 3)
235
+ *
236
+ * // Using HashSet.values to convert HashSet.HashSet<A> to IterableIterator<A>
237
+ * const iterable: IterableIterator<number> = HashSet.values(hashSet)
238
+ *
239
+ * console.log(...iterable) // Logs: 1 2 3
240
+ *
241
+ * // Using HashSet.toValues to convert HashSet.HashSet<A> to Array<A>
242
+ * const array: Array<number> = HashSet.toValues(hashSet)
243
+ *
244
+ * console.log(array) // Logs: [ 1, 2, 3 ]
245
+ * ```
246
+ *
247
+ * Be mindful of performance implications (both time and space complexity) when
248
+ * frequently converting between Effect's immutable HashSet and mutable
249
+ * JavaScript data structures, especially for large collections.
250
+ *
251
+ * @module HashSet
2
252
  * @since 2.0.0
3
253
  */
4
254
 
@@ -18,26 +268,78 @@ const TypeId: unique symbol = HS.HashSetTypeId as TypeId
18
268
  export type TypeId = typeof TypeId
19
269
 
20
270
  /**
271
+ * @memberof HashSet
21
272
  * @since 2.0.0
22
273
  * @category models
274
+ * @example **Syntax**
275
+ *
276
+ * ```ts
277
+ * import { HashSet } from "effect"
278
+ *
279
+ * let numberSet: HashSet.HashSet<number>
280
+ * ```
281
+ *
282
+ * @interface
23
283
  */
24
284
  export interface HashSet<out A> extends Iterable<A>, Equal, Pipeable, Inspectable {
25
285
  readonly [TypeId]: TypeId
26
286
  }
27
287
 
28
288
  /**
289
+ * @memberof HashSet
29
290
  * @since 2.0.0
30
291
  * @category refinements
31
292
  */
32
293
  export const isHashSet: {
33
294
  /**
34
- * @since 2.0.0
35
- * @category refinements
295
+ * Type guard function to determine if a given iterable is a `HashSet`.
296
+ *
297
+ * This overload preserves the type of the iterable's elements.
298
+ *
299
+ * @example
300
+ *
301
+ * ```ts
302
+ * import { HashSet } from "effect"
303
+ *
304
+ * const numberIterable: Iterable<1 | 2 | 3> = [1, 2, 3]
305
+ *
306
+ * if (
307
+ * // if passed an Iterable<A> the type guard that preserves the type parameter <A>
308
+ * HashSet.isHashSet(numberIterable)
309
+ * ) {
310
+ * const HashSet: HashSet.HashSet<1 | 2 | 3> = numberIterable
311
+ * }
312
+ * ```
313
+ *
314
+ * @param u - The iterable input to be checked.
315
+ * @returns A boolean indicating whether the provided iterable is a `HashSet`.
36
316
  */
37
317
  <A>(u: Iterable<A>): u is HashSet<A>
318
+
38
319
  /**
39
- * @since 2.0.0
40
- * @category refinements
320
+ * Type guard function that checks if the provided value is a `HashSet` of
321
+ * unknown type.
322
+ *
323
+ * @example
324
+ *
325
+ * ```ts
326
+ * import { HashSet } from "effect"
327
+ * import assert from "node:assert/strict"
328
+ *
329
+ * // Check if a value is a HashSet
330
+ * const set = HashSet.make(1, 2, 3)
331
+ *
332
+ * assert.equal(HashSet.isHashSet(set), true) // true
333
+ * assert.equal(HashSet.isHashSet(HashSet.empty()), true)
334
+ *
335
+ * // Works with any type
336
+ * assert.equal(HashSet.isHashSet(null), false) // false
337
+ * assert.equal(HashSet.isHashSet({}), false) // false
338
+ * assert.equal(HashSet.isHashSet([1, 2, 3]), false) // false
339
+ * ```
340
+ *
341
+ * @param u - The value to check.
342
+ * @returns A boolean indicating whether the value is a `HashSet<unknown>`.
41
343
  */
42
344
  (u: unknown): u is HashSet<unknown>
43
345
  } = HS.isHashSet
@@ -45,46 +347,270 @@ export const isHashSet: {
45
347
  /**
46
348
  * Creates an empty `HashSet`.
47
349
  *
350
+ * Time complexity: **`O(1)`**
351
+ *
352
+ * @memberof HashSet
48
353
  * @since 2.0.0
49
354
  * @category constructors
355
+ * @example
356
+ *
357
+ * ```ts
358
+ * import { HashSet, pipe } from "effect"
359
+ *
360
+ * console.log(
361
+ * pipe(
362
+ * // Provide a type argument to create a HashSet of a specific type
363
+ * HashSet.empty<number>(),
364
+ * HashSet.add(1),
365
+ * HashSet.add(1), // Notice the duplicate
366
+ * HashSet.add(2),
367
+ * HashSet.toValues
368
+ * )
369
+ * ) // Output: [1, 2]
370
+ * ```
371
+ *
372
+ * @see Other `HashSet` constructors are {@link make} {@link fromIterable}
50
373
  */
51
374
  export const empty: <A = never>() => HashSet<A> = HS.empty
52
375
 
53
376
  /**
54
377
  * Creates a new `HashSet` from an iterable collection of values.
55
378
  *
379
+ * Time complexity: **`O(n)`** where n is the number of elements in the iterable
380
+ *
381
+ * @memberof HashSet
56
382
  * @since 2.0.0
57
383
  * @category constructors
384
+ * @example Creating a HashSet from an {@link Array}
385
+ *
386
+ * ```ts
387
+ * import { HashSet, pipe } from "effect"
388
+ *
389
+ * console.log(
390
+ * pipe(
391
+ * [1, 2, 3, 4, 5, 1, 2, 3], // Array<number> is an Iterable<number>; Note the duplicates.
392
+ * HashSet.fromIterable,
393
+ * HashSet.toValues
394
+ * )
395
+ * ) // Output: [1, 2, 3, 4, 5]
396
+ * ```
397
+ *
398
+ * @example Creating a HashSet from a {@link Set}
399
+ *
400
+ * ```ts
401
+ * import { HashSet, pipe } from "effect"
402
+ *
403
+ * console.log(
404
+ * pipe(
405
+ * new Set(["apple", "banana", "orange", "apple"]), // Set<string> is an Iterable<string>
406
+ * HashSet.fromIterable,
407
+ * HashSet.toValues
408
+ * )
409
+ * ) // Output: ["apple", "banana", "orange"]
410
+ * ```
411
+ *
412
+ * @example Creating a HashSet from a {@link Generator}
413
+ *
414
+ * ```ts
415
+ * import { HashSet } from "effect"
416
+ *
417
+ * // Generator functions return iterables
418
+ * function* fibonacci(n: number): Generator<number, void, unknown> {
419
+ * let [a, b] = [0, 1]
420
+ * for (let i = 0; i < n; i++) {
421
+ * yield a
422
+ * ;[a, b] = [b, a + b]
423
+ * }
424
+ * }
425
+ *
426
+ * // Create a HashSet from the first 10 Fibonacci numbers
427
+ * const fibonacciSet = HashSet.fromIterable(fibonacci(10))
428
+ *
429
+ * console.log(HashSet.toValues(fibonacciSet))
430
+ * // Outputs: [0, 1, 2, 3, 5, 8, 13, 21, 34] but in unsorted order
431
+ * ```
432
+ *
433
+ * @example Creating a HashSet from another {@link HashSet}
434
+ *
435
+ * ```ts
436
+ * import { HashSet, pipe } from "effect"
437
+ *
438
+ * console.log(
439
+ * pipe(
440
+ * // since HashSet implements the Iterable interface, we can use it to create a new HashSet
441
+ * HashSet.make(1, 2, 3, 4),
442
+ * HashSet.fromIterable,
443
+ * HashSet.toValues // turns the HashSet back into an array
444
+ * )
445
+ * ) // Output: [1, 2, 3, 4]
446
+ * ```
447
+ *
448
+ * @example Creating a HashSet from other Effect's data structures like
449
+ * {@link Chunk}
450
+ *
451
+ * ```ts
452
+ * import { Chunk, HashSet, pipe } from "effect"
453
+ *
454
+ * console.log(
455
+ * pipe(
456
+ * Chunk.make(1, 2, 3, 4), // Iterable<number>
457
+ * HashSet.fromIterable,
458
+ * HashSet.toValues // turns the HashSet back into an array
459
+ * )
460
+ * ) // Outputs: [1, 2, 3, 4]
461
+ * ```
462
+ *
463
+ * @see Other `HashSet` constructors are {@link empty} {@link make}
58
464
  */
59
465
  export const fromIterable: <A>(elements: Iterable<A>) => HashSet<A> = HS.fromIterable
60
466
 
61
467
  /**
62
468
  * Construct a new `HashSet` from a variable number of values.
63
469
  *
470
+ * Time complexity: **`O(n)`** where n is the number of elements
471
+ *
472
+ * @memberof HashSet
64
473
  * @since 2.0.0
65
474
  * @category constructors
475
+ * @example
476
+ *
477
+ * ```ts
478
+ * import { Equal, Hash, HashSet, pipe } from "effect"
479
+ * import assert from "node:assert/strict"
480
+ *
481
+ * class Character implements Equal.Equal {
482
+ * readonly name: string
483
+ * readonly trait: string
484
+ *
485
+ * constructor(name: string, trait: string) {
486
+ * this.name = name
487
+ * this.trait = trait
488
+ * }
489
+ *
490
+ * // Define equality based on name, and trait
491
+ * [Equal.symbol](that: Equal.Equal): boolean {
492
+ * if (that instanceof Character) {
493
+ * return (
494
+ * Equal.equals(this.name, that.name) &&
495
+ * Equal.equals(this.trait, that.trait)
496
+ * )
497
+ * }
498
+ * return false
499
+ * }
500
+ *
501
+ * // Generate a hash code based on the sum of the character's name and trait
502
+ * [Hash.symbol](): number {
503
+ * return Hash.hash(this.name + this.trait)
504
+ * }
505
+ *
506
+ * static readonly of = (name: string, trait: string): Character => {
507
+ * return new Character(name, trait)
508
+ * }
509
+ * }
510
+ *
511
+ * assert.strictEqual(
512
+ * Equal.equals(
513
+ * HashSet.make(
514
+ * Character.of("Alice", "Curious"),
515
+ * Character.of("Alice", "Curious"),
516
+ * Character.of("White Rabbit", "Always late"),
517
+ * Character.of("Mad Hatter", "Tea enthusiast")
518
+ * ),
519
+ * // Is the same as adding each character to an empty set
520
+ * pipe(
521
+ * HashSet.empty(),
522
+ * HashSet.add(Character.of("Alice", "Curious")),
523
+ * HashSet.add(Character.of("Alice", "Curious")), // Alice tried to attend twice!
524
+ * HashSet.add(Character.of("White Rabbit", "Always late")),
525
+ * HashSet.add(Character.of("Mad Hatter", "Tea enthusiast"))
526
+ * )
527
+ * ),
528
+ * true,
529
+ * "`HashSet.make` and `HashSet.empty() + HashSet.add()` should be equal"
530
+ * )
531
+ *
532
+ * assert.strictEqual(
533
+ * Equal.equals(
534
+ * HashSet.make(
535
+ * Character.of("Alice", "Curious"),
536
+ * Character.of("Alice", "Curious"),
537
+ * Character.of("White Rabbit", "Always late"),
538
+ * Character.of("Mad Hatter", "Tea enthusiast")
539
+ * ),
540
+ * HashSet.fromIterable([
541
+ * Character.of("Alice", "Curious"),
542
+ * Character.of("Alice", "Curious"),
543
+ * Character.of("White Rabbit", "Always late"),
544
+ * Character.of("Mad Hatter", "Tea enthusiast")
545
+ * ])
546
+ * ),
547
+ * true,
548
+ * "`HashSet.make` and `HashSet.fromIterable` should be equal"
549
+ * )
550
+ * ```
551
+ *
552
+ * @see Other `HashSet` constructors are {@linkcode fromIterable} {@linkcode empty}
66
553
  */
67
554
  export const make: <As extends ReadonlyArray<any>>(...elements: As) => HashSet<As[number]> = HS.make
68
555
 
69
556
  /**
70
557
  * Checks if the specified value exists in the `HashSet`.
71
558
  *
559
+ * Time complexity: **`O(1)`** average
560
+ *
561
+ * @memberof HashSet
72
562
  * @since 2.0.0
73
563
  * @category elements
564
+ * @example **syntax**
565
+ *
566
+ * ```ts
567
+ * import { HashSet, pipe } from "effect"
568
+ *
569
+ * // with `data-last`, a.k.a. `pipeable` API
570
+ * pipe(HashSet.make(0, 1, 2), HashSet.has(3)) // false
571
+ *
572
+ * // or piped with the pipe function
573
+ * HashSet.make(0, 1, 2).pipe(HashSet.has(3)) // false
574
+ *
575
+ * // or with `data-first` API
576
+ * HashSet.has(HashSet.make(0, 1, 2), 3) // false
577
+ * ```
578
+ *
579
+ * @returns A `boolean` signaling the presence of the value in the HashSet
580
+ * @see Other `HashSet` elements are {@link some} {@link every} {@link isSubset}
74
581
  */
75
582
  export const has: {
76
583
  /**
77
- * Checks if the specified value exists in the `HashSet`.
584
+ * @example {@link has} `data-last` a.k.a. `pipeable` API
78
585
  *
79
- * @since 2.0.0
80
- * @category elements
586
+ * ```ts
587
+ * import * as assert from "node:assert/strict"
588
+ * import { HashSet, pipe } from "effect"
589
+ *
590
+ * const set = HashSet.make(0, 1, 2)
591
+ *
592
+ * assert.equal(pipe(set, HashSet.has(0)), true)
593
+ * assert.equal(pipe(set, HashSet.has(1)), true)
594
+ * assert.equal(pipe(set, HashSet.has(2)), true)
595
+ * assert.equal(pipe(set, HashSet.has(3)), false)
596
+ * ```
81
597
  */
82
598
  <A>(value: A): (self: HashSet<A>) => boolean
599
+
83
600
  /**
84
- * Checks if the specified value exists in the `HashSet`.
601
+ * @example {@link has} `data-first` API
85
602
  *
86
- * @since 2.0.0
87
- * @category elements
603
+ * ```ts
604
+ * import * as assert from "node:assert/strict"
605
+ * import { HashSet, pipe } from "effect"
606
+ *
607
+ * const set = HashSet.make(0, 1, 2)
608
+ *
609
+ * assert.equal(HashSet.has(set, 0), true)
610
+ * assert.equal(HashSet.has(set, 1), true)
611
+ * assert.equal(HashSet.has(set, 2), true)
612
+ * assert.equal(HashSet.has(set, 3), false)
613
+ * ```
88
614
  */
89
615
  <A>(self: HashSet<A>, value: A): boolean
90
616
  } = HS.has
@@ -92,22 +618,81 @@ export const has: {
92
618
  /**
93
619
  * Check if a predicate holds true for some `HashSet` element.
94
620
  *
621
+ * Time complexity: **`O(n)`** where n is the number of elements in the set
622
+ *
623
+ * @memberof HashSet
95
624
  * @since 2.0.0
96
625
  * @category elements
626
+ * @example **syntax**
627
+ *
628
+ * ```ts
629
+ * import { HashSet, pipe } from "effect"
630
+ *
631
+ * const set: HashSet.HashSet<number> = HashSet.make(0, 1, 2)
632
+ *
633
+ * // with `data-last`, a.k.a. `pipeable` API
634
+ * pipe(
635
+ * set,
636
+ * HashSet.some((n) => n > 0)
637
+ * ) // true
638
+ *
639
+ * // or piped with the pipe function
640
+ * set.pipe(HashSet.some((n) => n > 0)) // true
641
+ *
642
+ * // or with `data-first` API
643
+ * HashSet.some(set, (n) => n > 0) // true
644
+ * ```
645
+ *
646
+ * @see Other `HashSet` elements are {@link has} {@link every} {@link isSubset}
97
647
  */
98
648
  export const some: {
99
649
  /**
100
- * Check if a predicate holds true for some `HashSet` element.
650
+ * @example {@link some} `data-last` a.k.a. `pipeable` API
651
+ *
652
+ * ```ts
653
+ * import * as assert from "node:assert/strict"
654
+ * import { HashSet, pipe } from "effect"
655
+ *
656
+ * const set = HashSet.make(0, 1, 2)
657
+ *
658
+ * assert.equal(
659
+ * pipe(
660
+ * set,
661
+ * HashSet.some((n) => n > 0)
662
+ * ),
663
+ * true
664
+ * )
101
665
  *
102
- * @since 2.0.0
103
- * @category elements
666
+ * assert.equal(
667
+ * pipe(
668
+ * set,
669
+ * HashSet.some((n) => n > 2)
670
+ * ),
671
+ * false
672
+ * )
673
+ * ```
104
674
  */
105
675
  <A>(f: Predicate<A>): (self: HashSet<A>) => boolean
676
+
106
677
  /**
107
- * Check if a predicate holds true for some `HashSet` element.
678
+ * @example {@link some} `data-first` API
679
+ *
680
+ * ```ts
681
+ * import * as assert from "node:assert/strict"
682
+ * import { HashSet } from "effect"
683
+ *
684
+ * const set = HashSet.make(0, 1, 2)
108
685
  *
109
- * @since 2.0.0
110
- * @category elements
686
+ * assert.equal(
687
+ * HashSet.some(set, (n) => n > 0),
688
+ * true
689
+ * )
690
+ *
691
+ * assert.equal(
692
+ * HashSet.some(set, (n) => n > 2),
693
+ * false
694
+ * )
695
+ * ```
111
696
  */
112
697
  <A>(self: HashSet<A>, f: Predicate<A>): boolean
113
698
  } = HS.some
@@ -115,36 +700,150 @@ export const some: {
115
700
  /**
116
701
  * Check if a predicate holds true for every `HashSet` element.
117
702
  *
703
+ * Time complexity is **`O(n)`** as it needs to traverse the whole HashSet
704
+ * collection
705
+ *
706
+ * @memberof HashSet
118
707
  * @since 2.0.0
119
708
  * @category elements
709
+ * @example **syntax** with {@link Refinement}
710
+ *
711
+ * ```ts
712
+ * import { HashSet, pipe, Predicate } from "effect"
713
+ *
714
+ * const numberOrString = HashSet.make(1, "1", "one", "uno")
715
+ *
716
+ * // with `data-last`, a.k.a. `pipeable` API and `Refinement`
717
+ * pipe(
718
+ * numberOrString, // HashSet.HashSet<number | string>
719
+ * HashSet.every(Predicate.isString)
720
+ * ) // HashSet.HashSet<string>
721
+ *
722
+ * // or piped with the pipe function and `Refinement`
723
+ * numberOrString // HashSet.HashSet<number | string>
724
+ * .pipe(HashSet.every(Predicate.isString)) // HashSet.HashSet<string>
725
+ *
726
+ * // or with `data-first` API and `Refinement`
727
+ * HashSet.every(
728
+ * numberOrString, // HashSet.HashSet<number | string>
729
+ * Predicate.isString
730
+ * ) // HashSet.HashSet<string>
731
+ * ```
732
+ *
733
+ * @example **syntax** with {@link Predicate}
734
+ *
735
+ * ```ts
736
+ * import { HashSet, pipe } from "effect"
737
+ *
738
+ * const set = HashSet.make(1, 2, 3)
739
+ *
740
+ * // with `data-last`, a.k.a. `pipeable` API
741
+ * pipe(
742
+ * set,
743
+ * HashSet.every((n) => n >= 0)
744
+ * ) // true
745
+ *
746
+ * // or piped with the pipe function
747
+ * set.pipe(HashSet.every((n) => n >= 0)) // true
748
+ *
749
+ * // or with `data-first` API
750
+ * HashSet.every(set, (n) => n >= 0) // true
751
+ * ```
752
+ *
753
+ * @returns A boolean once it has evaluated that whole collection fulfill the
754
+ * Predicate function
755
+ * @see Other `HashSet` elements are {@link has} {@link some} {@link isSubset}
120
756
  */
121
757
  export const every: {
122
758
  /**
123
- * Check if a predicate holds true for every `HashSet` element.
759
+ * @example
760
+ *
761
+ * ```ts
762
+ * import * as assert from "node:assert/strict"
763
+ * import { Effect, HashSet, pipe, Predicate } from "effect"
124
764
  *
125
- * @since 2.0.0
126
- * @category elements
765
+ * const numberOrString: HashSet.HashSet<number | string> = HashSet.make(
766
+ * 1,
767
+ * "1",
768
+ * "one",
769
+ * "uno"
770
+ * )
771
+ *
772
+ * assert.equal(
773
+ * pipe(
774
+ * numberOrString, // HashSet.HashSet<number | string>
775
+ * HashSet.every(Predicate.isString)
776
+ * ), // HashSet.HashSet<string>
777
+ * false
778
+ * )
779
+ * ```
127
780
  */
128
- <A, B extends A>(refinement: Refinement<NoInfer<A>, B>): (self: HashSet<A>) => self is HashSet<B>
781
+ <A, B extends A>(
782
+ refinement: Refinement<NoInfer<A>, B>
783
+ ): (self: HashSet<A>) => self is HashSet<B>
784
+
129
785
  /**
130
- * Check if a predicate holds true for every `HashSet` element.
786
+ * @example
787
+ *
788
+ * ```ts
789
+ * import * as assert from "node:assert/strict"
790
+ * import { HashSet, pipe } from "effect"
131
791
  *
132
- * @since 2.0.0
133
- * @category elements
792
+ * const set = HashSet.make(0, 1, 2)
793
+ *
794
+ * assert.equal(
795
+ * pipe(
796
+ * set,
797
+ * HashSet.every((n) => n >= 0)
798
+ * ),
799
+ * true
800
+ * )
801
+ * ```
134
802
  */
135
803
  <A>(predicate: Predicate<A>): (self: HashSet<A>) => boolean
804
+
136
805
  /**
137
- * Check if a predicate holds true for every `HashSet` element.
806
+ * @example
807
+ *
808
+ * ```ts
809
+ * import * as assert from "node:assert/strict"
810
+ * import { Effect, HashSet, pipe, Predicate } from "effect"
138
811
  *
139
- * @since 2.0.0
140
- * @category elements
812
+ * const numberOrString: HashSet.HashSet<number | string> = HashSet.make(
813
+ * 1,
814
+ * "1",
815
+ * "one",
816
+ * "uno"
817
+ * )
818
+ *
819
+ * assert.equal(
820
+ * HashSet.every(
821
+ * numberOrString, // HashSet.HashSet<number | string>
822
+ * Predicate.isString
823
+ * ), // HashSet.HashSet<string>
824
+ * false
825
+ * )
826
+ * ```
141
827
  */
142
- <A, B extends A>(self: HashSet<A>, refinement: Refinement<A, B>): self is HashSet<B>
828
+ <A, B extends A>(
829
+ self: HashSet<A>,
830
+ refinement: Refinement<A, B>
831
+ ): self is HashSet<B>
832
+
143
833
  /**
144
- * Check if a predicate holds true for every `HashSet` element.
834
+ * @example
835
+ *
836
+ * ```ts
837
+ * import * as assert from "node:assert/strict"
838
+ * import { HashSet } from "effect"
145
839
  *
146
- * @since 2.0.0
147
- * @category elements
840
+ * const set = HashSet.make(0, 1, 2)
841
+ *
842
+ * assert.equal(
843
+ * HashSet.every(set, (n) => n >= 0),
844
+ * true
845
+ * )
846
+ * ```
148
847
  */
149
848
  <A>(self: HashSet<A>, predicate: Predicate<A>): boolean
150
849
  } = HS.every
@@ -155,28 +854,73 @@ export const every: {
155
854
  *
156
855
  * **NOTE**: the hash and equal of both sets must be the same.
157
856
  *
857
+ * Time complexity analysis is of **`O(n)`**
858
+ *
859
+ * @memberof HashSet
158
860
  * @since 2.0.0
159
861
  * @category elements
862
+ * @example **Syntax**
863
+ *
864
+ * ```ts
865
+ * import { HashSet, pipe } from "effect"
866
+ *
867
+ * const set1 = HashSet.make(0, 1)
868
+ * const set2 = HashSet.make(1, 2)
869
+ * const set3 = HashSet.make(0, 1, 2)
870
+ *
871
+ * // with `data-last`, a.k.a. `pipeable` API
872
+ * pipe(set1, HashSet.isSubset(set2)) // false
873
+ * pipe(set1, HashSet.isSubset(set3)) // true
874
+ *
875
+ * // or piped with the pipe function
876
+ * set1.pipe(HashSet.isSubset(set2)) // false
877
+ * set1.pipe(HashSet.isSubset(set3)) // true
878
+ *
879
+ * // or with `data-first` API
880
+ * HashSet.isSubset(set1, set2) // false
881
+ * HashSet.isSubset(set1, set3) // true)
882
+ * ```
883
+ *
884
+ * @see Other `HashSet` elements are {@link has} {@link some} {@link every}
160
885
  */
161
886
  export const isSubset: {
162
887
  /**
163
- * Returns `true` if and only if every element in the this `HashSet` is an
164
- * element of the second set,
888
+ * @example
889
+ *
890
+ * ```ts
891
+ * import { HashSet, pipe } from "effect"
892
+ * import * as assert from "node:assert/strict"
165
893
  *
166
- * **NOTE**: the hash and equal of both sets must be the same.
894
+ * assert.equal(
895
+ * pipe(
896
+ * HashSet.make(0, 1), //
897
+ * HashSet.isSubset(HashSet.make(1, 2))
898
+ * ),
899
+ * false
900
+ * )
167
901
  *
168
- * @since 2.0.0
169
- * @category elements
902
+ * assert.equal(
903
+ * pipe(
904
+ * HashSet.make(0, 1), //
905
+ * HashSet.isSubset(HashSet.make(0, 1, 2))
906
+ * ),
907
+ * true
908
+ * )
909
+ * ```
170
910
  */
171
911
  <A>(that: HashSet<A>): (self: HashSet<A>) => boolean
912
+
172
913
  /**
173
- * Returns `true` if and only if every element in the this `HashSet` is an
174
- * element of the second set,
914
+ * @example
915
+ *
916
+ * ```ts
917
+ * import { HashSet } from "effect"
918
+ * import * as assert from "node:assert/strict"
175
919
  *
176
- * **NOTE**: the hash and equal of both sets must be the same.
920
+ * assert.equal(HashSet.isSubset(set1, set2), false)
177
921
  *
178
- * @since 2.0.0
179
- * @category elements
922
+ * assert.equal(HashSet.isSubset(set1, set3), true)
923
+ * ```
180
924
  */
181
925
  <A>(self: HashSet<A>, that: HashSet<A>): boolean
182
926
  } = HS.isSubset
@@ -184,57 +928,283 @@ export const isSubset: {
184
928
  /**
185
929
  * Returns an `IterableIterator` of the values in the `HashSet`.
186
930
  *
931
+ * Time complexity: **`O(1)`**
932
+ *
933
+ * @memberof HashSet
187
934
  * @since 2.0.0
188
935
  * @category getters
936
+ * @example
937
+ *
938
+ * ```ts
939
+ * import { HashSet, pipe } from "effect"
940
+ *
941
+ * const numberIterable = pipe(
942
+ * HashSet.make(0, 1, 1, 2), // HashSet.HashSet<number>
943
+ * HashSet.values // takes an HashSet<A> and returns an IterableIterator<A>
944
+ * )
945
+ *
946
+ * for (const number of numberIterable) {
947
+ * console.log(number) // it will logs: 0, 1, 2
948
+ * }
949
+ * ```
950
+ *
951
+ * @see Other `HashSet` getters are {@link toValues} {@link size}
189
952
  */
190
953
  export const values: <A>(self: HashSet<A>) => IterableIterator<A> = HS.values
191
954
 
192
955
  /**
193
956
  * Returns an `Array` of the values within the `HashSet`.
194
957
  *
958
+ * Time complexity: **`O(n)`** where n is the number of elements in the set
959
+ *
960
+ * @memberof HashSet
195
961
  * @since 3.13.0
196
962
  * @category getters
963
+ * @example
964
+ *
965
+ * ```ts
966
+ * import { HashSet, pipe } from "effect"
967
+ * import { deepStrictEqual } from "node:assert/strict"
968
+ *
969
+ * deepStrictEqual(
970
+ * pipe(
971
+ * HashSet.make(0, 1, 1, 2), // HashSet<number>
972
+ * HashSet.toValues // takes an HashSet<A> and returns an Array<A>
973
+ * ),
974
+ * Array.of(0, 1, 2)
975
+ * )
976
+ * ```
977
+ *
978
+ * @see Other `HashSet` getters are {@link values} {@link size}
197
979
  */
198
980
  export const toValues = <A>(self: HashSet<A>): Array<A> => Array.from(values(self))
199
981
 
200
982
  /**
201
983
  * Calculates the number of values in the `HashSet`.
202
984
  *
985
+ * Time complexity: **`O(1)`**
986
+ *
987
+ * @memberof HashSet
203
988
  * @since 2.0.0
204
989
  * @category getters
990
+ * @example
991
+ *
992
+ * ```ts
993
+ * import { HashSet, pipe } from "effect"
994
+ * import assert from "node:assert/strict"
995
+ *
996
+ * assert.deepStrictEqual(pipe(HashSet.empty(), HashSet.size), 0)
997
+ *
998
+ * assert.deepStrictEqual(
999
+ * pipe(HashSet.make(1, 2, 2, 3, 4, 3), HashSet.size),
1000
+ * 4
1001
+ * )
1002
+ * ```
1003
+ *
1004
+ * @see Other `HashSet` getters are {@link values} {@link toValues}
205
1005
  */
206
1006
  export const size: <A>(self: HashSet<A>) => number = HS.size
207
1007
 
208
1008
  /**
209
- * Marks the `HashSet` as mutable.
1009
+ * Creates a new mutable version of the `HashSet`
1010
+ *
1011
+ * When a `HashSet` is mutable, operations like {@link add} and {@link remove}
1012
+ * modify the data structure in place instead of creating a new one, which is
1013
+ * more efficient when performing multiple operations.
210
1014
  *
1015
+ * @memberof HashSet
211
1016
  * @since 2.0.0
1017
+ * @example
1018
+ *
1019
+ * ```ts
1020
+ * import { HashSet } from "effect"
1021
+ * import assert from "node:assert/strict"
1022
+ *
1023
+ * const UPPER_BOUND = 10_000
1024
+ *
1025
+ * const immutableSet = HashSet.empty<number>().pipe(HashSet.add(0))
1026
+ *
1027
+ * // Create a mutable version of the immutableSet
1028
+ * const mutableSet = HashSet.beginMutation(immutableSet)
1029
+ *
1030
+ * for (let i = 1; i < UPPER_BOUND; i++) {
1031
+ * // Operations now modify the set in place instead of creating new instances
1032
+ * // This is more efficient when making multiple changes
1033
+ * const pointerToMutableSet = HashSet.add(mutableSet, i)
1034
+ *
1035
+ * // the two sets have the same identity, hence `add` is mutating mutableSet and not returning a new HashSet instance
1036
+ * assert(Object.is(mutableSet, pointerToMutableSet))
1037
+ * assert.equal(HashSet.has(mutableSet, i), true) // `i` is in the mutableSet
1038
+ * assert.equal(HashSet.has(immutableSet, i), false) // `i` is not in the immutableSet
1039
+ * }
1040
+ *
1041
+ * const next = UPPER_BOUND + 1
1042
+ * // When done, mark the set as immutable again
1043
+ * HashSet.endMutation(mutableSet).pipe(
1044
+ * HashSet.add(next) // since this returns a new HashSet, it will not be logged as part of the mutableSet
1045
+ * )
1046
+ * assert.equal(HashSet.has(mutableSet, next), false)
1047
+ *
1048
+ * console.log(HashSet.toValues(immutableSet)) // [0]
1049
+ * console.log(HashSet.toValues(mutableSet).sort((a, b) => a - b)) // [0, 1, 2, 3, ...rest]
1050
+ * ```
1051
+ *
1052
+ * @see Other `HashSet` mutations are {@link add} {@link remove} {@link toggle} {@link endMutation} {@link mutate}
212
1053
  */
213
1054
  export const beginMutation: <A>(self: HashSet<A>) => HashSet<A> = HS.beginMutation
214
1055
 
215
1056
  /**
216
- * Marks the `HashSet` as immutable.
1057
+ * Makes the `HashSet` immutable again.
1058
+ *
1059
+ * After calling `endMutation`, operations like {@link add} and {@link remove}
1060
+ * will create new instances of the `HashSet` instead of modifying the existing
1061
+ * one.
217
1062
  *
1063
+ * @memberof HashSet
218
1064
  * @since 2.0.0
1065
+ * @example
1066
+ *
1067
+ * ```ts
1068
+ * import { HashSet } from "effect"
1069
+ * import assert from "node:assert/strict"
1070
+ *
1071
+ * // Create a mutable set
1072
+ * const mutableSet = HashSet.beginMutation(HashSet.empty<number>())
1073
+ *
1074
+ * // Add some elements to the mutable set
1075
+ * HashSet.add(mutableSet, 1)
1076
+ * HashSet.add(mutableSet, 2)
1077
+ *
1078
+ * // Before endMutation, operations modify the set in place
1079
+ * const sameSet = HashSet.add(mutableSet, 3)
1080
+ * assert(Object.is(mutableSet, sameSet)) // true - same object reference
1081
+ * assert.deepStrictEqual(HashSet.toValues(mutableSet).sort(), [1, 2, 3])
1082
+ *
1083
+ * // Make the set immutable again
1084
+ * const immutableSet = HashSet.endMutation(mutableSet)
1085
+ *
1086
+ * // endMutation returns the same set instance, now made immutable
1087
+ * assert(Object.is(mutableSet, immutableSet)) // true - same object reference
1088
+ *
1089
+ * // After endMutation, operations create new instances
1090
+ * const newSet = HashSet.add(immutableSet, 4)
1091
+ * assert(!Object.is(immutableSet, newSet)) // false - different object references
1092
+ *
1093
+ * // The original set remains unchanged
1094
+ * assert.deepStrictEqual(HashSet.toValues(immutableSet).sort(), [1, 2, 3])
1095
+ *
1096
+ * // The new set contains the added element
1097
+ * assert.deepStrictEqual(HashSet.toValues(newSet).sort(), [1, 2, 3, 4])
1098
+ * ```
1099
+ *
1100
+ * @see Other `HashSet` mutations are {@linkcode HashSet.add} {@linkcode HashSet.remove} {@linkcode HashSet.toggle} {@linkcode HashSet.beginMutation} {@linkcode HashSet.mutate}
219
1101
  */
220
1102
  export const endMutation: <A>(self: HashSet<A>) => HashSet<A> = HS.endMutation
221
1103
 
222
1104
  /**
223
1105
  * Mutates the `HashSet` within the context of the provided function.
224
1106
  *
1107
+ * You can consider it a functional abstraction on top of the lower-level
1108
+ * mutation primitives of {@linkcode HashSet.beginMutation} `->` `mutable
1109
+ * context` `->` {@linkcode HashSet.endMutation}.
1110
+ *
1111
+ * @memberof HashSet
225
1112
  * @since 2.0.0
1113
+ * @example **Syntax**
1114
+ *
1115
+ * ```ts
1116
+ * import { HashSet, pipe } from "effect"
1117
+ *
1118
+ * // with data-last, a.k.a. pipeable API
1119
+ * pipe(
1120
+ * HashSet.make(1, 2, 3),
1121
+ * HashSet.mutate((set) => {
1122
+ * HashSet.add(set, 4)
1123
+ * HashSet.remove(set, 1)
1124
+ * })
1125
+ * )
1126
+ *
1127
+ * // or piped with the pipe function
1128
+ * HashSet.make(1, 2, 3).pipe(
1129
+ * HashSet.mutate((set) => {
1130
+ * HashSet.add(set, 4)
1131
+ * HashSet.remove(set, 1)
1132
+ * })
1133
+ * )
1134
+ *
1135
+ * // or with data-first API
1136
+ * HashSet.mutate(HashSet.make(1, 2, 3), (set) => {
1137
+ * HashSet.add(set, 4)
1138
+ * HashSet.remove(set, 1)
1139
+ * })
1140
+ * ```
1141
+ *
1142
+ * @see Other `HashSet` mutations are {@linkcode HashSet.add} {@linkcode HashSet.remove} {@linkcode HashSet.toggle} {@linkcode HashSet.beginMutation} {@linkcode HashSet.endMutation}
226
1143
  */
227
1144
  export const mutate: {
228
1145
  /**
229
- * Mutates the `HashSet` within the context of the provided function.
1146
+ * @example {@linkcode HashSet.mutate} `data-last` a.k.a. `pipeable` API
230
1147
  *
231
- * @since 2.0.0
1148
+ * ```ts
1149
+ * import { HashSet, pipe } from "effect"
1150
+ * import assert from "node:assert/strict"
1151
+ *
1152
+ * // Create a set with initial values
1153
+ * const immutableSet = HashSet.make(1, 2, 3)
1154
+ *
1155
+ * // Use mutate to perform multiple operations efficiently
1156
+ * const result = pipe(
1157
+ * immutableSet,
1158
+ * HashSet.mutate((set) => {
1159
+ * assert.equal(Object.is(immutableSet, set), false)
1160
+ *
1161
+ * // The set is temporarily mutable inside this function
1162
+ * const mod1 = HashSet.add(set, 4)
1163
+ * const mod2 = HashSet.remove(set, 1)
1164
+ * assert.equal(Object.is(mod1, mod2), true) // they are the same object by reference
1165
+ * })
1166
+ * )
1167
+ *
1168
+ * // The original set is unchanged
1169
+ * assert.equal(Object.is(immutableSet, result), false)
1170
+ * assert.deepStrictEqual(
1171
+ * HashSet.toValues(immutableSet).sort(),
1172
+ * [1, 2, 3]
1173
+ * )
1174
+ *
1175
+ * // The result contains the mutations
1176
+ * assert.deepStrictEqual(HashSet.toValues(result).sort(), [2, 3, 4])
1177
+ * ```
232
1178
  */
233
1179
  <A>(f: (set: HashSet<A>) => void): (self: HashSet<A>) => HashSet<A>
1180
+
234
1181
  /**
235
- * Mutates the `HashSet` within the context of the provided function.
1182
+ * @example {@linkcode HashSet.mutate} `data-first` API
236
1183
  *
237
- * @since 2.0.0
1184
+ * ```ts
1185
+ * import { HashSet } from "effect"
1186
+ * import assert from "node:assert/strict"
1187
+ *
1188
+ * // Create a set with initial values
1189
+ * const immutableSet = HashSet.make(1, 2, 3)
1190
+ *
1191
+ * // Use mutate with data-first API
1192
+ * const result = HashSet.mutate(immutableSet, (set) => {
1193
+ * // The set is temporarily mutable inside this function
1194
+ * HashSet.add(set, 4)
1195
+ * HashSet.remove(set, 1)
1196
+ * })
1197
+ *
1198
+ * // The original set is unchanged
1199
+ * assert.equal(Object.is(immutableSet, result), false)
1200
+ * assert.deepStrictEqual(
1201
+ * HashSet.toValues(immutableSet).sort(),
1202
+ * [1, 2, 3]
1203
+ * )
1204
+ *
1205
+ * // The result contains the mutations
1206
+ * assert.deepStrictEqual(HashSet.toValues(result).sort(), [2, 3, 4])
1207
+ * ```
238
1208
  */
239
1209
  <A>(self: HashSet<A>, f: (set: HashSet<A>) => void): HashSet<A>
240
1210
  } = HS.mutate
@@ -242,19 +1212,72 @@ export const mutate: {
242
1212
  /**
243
1213
  * Adds a value to the `HashSet`.
244
1214
  *
1215
+ * Time complexity: **`O(1)`** average
1216
+ *
1217
+ * @remarks
1218
+ * Remember that a `HashSet` is a collection of unique values, so adding a value
1219
+ * that already exists in the `HashSet` will not add a duplicate.
1220
+ *
1221
+ * Remember that HashSet is an immutable data structure, so the `add` function,
1222
+ * like all other functions that modify the HashSet, will return a new HashSet
1223
+ * with the added value.
1224
+ * @memberof HashSet
245
1225
  * @since 2.0.0
1226
+ * @example **Syntax**
1227
+ *
1228
+ * ```ts
1229
+ * import { HashSet, pipe } from "effect"
1230
+ *
1231
+ * // with data-last, a.k.a. pipeable API
1232
+ * pipe(HashSet.empty(), HashSet.add(0), HashSet.add(0))
1233
+ *
1234
+ * // or piped with the pipe function
1235
+ * HashSet.empty().pipe(HashSet.add(0))
1236
+ *
1237
+ * // or with data-first API
1238
+ * HashSet.add(HashSet.empty(), 0)
1239
+ * ```
1240
+ *
1241
+ * @see Other `HashSet` mutations are {@link remove} {@link toggle} {@link beginMutation} {@link endMutation} {@link mutate}
246
1242
  */
247
1243
  export const add: {
248
1244
  /**
249
- * Adds a value to the `HashSet`.
1245
+ * @example {@link add} `data-last` a.k.a. `pipeable` API
1246
+ *
1247
+ * ```ts
1248
+ * import { HashSet, pipe } from "effect"
1249
+ * import assert from "node:assert/strict"
250
1250
  *
251
- * @since 2.0.0
1251
+ * assert.deepStrictEqual(
1252
+ * pipe(
1253
+ * HashSet.empty<number>(), // HashSet.HashSet<number>
1254
+ * HashSet.add(0),
1255
+ * HashSet.add(1),
1256
+ * HashSet.add(1),
1257
+ * HashSet.add(2),
1258
+ * HashSet.toValues
1259
+ * ),
1260
+ * Array.of(0, 1, 2)
1261
+ * )
1262
+ * ```
252
1263
  */
253
1264
  <A>(value: A): (self: HashSet<A>) => HashSet<A>
1265
+
254
1266
  /**
255
- * Adds a value to the `HashSet`.
1267
+ * @example {@link add} `data-first` API
1268
+ *
1269
+ * ```ts
1270
+ * import { HashSet, pipe } from "effect"
1271
+ * import assert from "node:assert/strict"
1272
+ *
1273
+ * const empty = HashSet.empty<number>()
1274
+ * const withZero = HashSet.add(empty, 0)
1275
+ * const withOne = HashSet.add(withZero, 1)
1276
+ * const withTwo = HashSet.add(withOne, 2)
1277
+ * const withTwoTwo = HashSet.add(withTwo, 2)
256
1278
  *
257
- * @since 2.0.0
1279
+ * assert.deepStrictEqual(HashSet.toValues(withTwoTwo), Array.of(0, 1, 2))
1280
+ * ```
258
1281
  */
259
1282
  <A>(self: HashSet<A>, value: A): HashSet<A>
260
1283
  } = HS.add
@@ -262,115 +1285,352 @@ export const add: {
262
1285
  /**
263
1286
  * Removes a value from the `HashSet`.
264
1287
  *
1288
+ * Time complexity: **`O(1)`** average
1289
+ *
1290
+ * @memberof HashSet
265
1291
  * @since 2.0.0
1292
+ * @example **Syntax**
1293
+ *
1294
+ * ```ts
1295
+ * import { HashSet, pipe } from "effect"
1296
+ *
1297
+ * // with `data-last`, a.k.a. `pipeable` API
1298
+ * pipe(HashSet.make(0, 1, 2), HashSet.remove(0))
1299
+ *
1300
+ * // or piped with the pipe function
1301
+ * HashSet.make(0, 1, 2).pipe(HashSet.remove(0))
1302
+ *
1303
+ * // or with `data-first` API
1304
+ * HashSet.remove(HashSet.make(0, 1, 2), 0)
1305
+ * ```
1306
+ *
1307
+ * @see Other `HashSet` mutations are {@link add} {@link toggle} {@link beginMutation} {@link endMutation} {@link mutate}
266
1308
  */
267
1309
  export const remove: {
268
1310
  /**
269
- * Removes a value from the `HashSet`.
1311
+ * @example {@link remove} `data-last` a.k.a. `pipeable` API
270
1312
  *
271
- * @since 2.0.0
1313
+ * ```ts
1314
+ * import { HashSet, pipe } from "effect"
1315
+ * import * as assert from "node:assert/strict"
1316
+ *
1317
+ * const set = HashSet.make(0, 1, 2)
1318
+ * const result = pipe(set, HashSet.remove(0))
1319
+ *
1320
+ * assert.equal(pipe(result, HashSet.has(0)), false) // it has correctly removed 0
1321
+ * assert.equal(pipe(set, HashSet.has(0)), true) // it does not mutate the original set
1322
+ * assert.equal(pipe(result, HashSet.has(1)), true)
1323
+ * assert.equal(pipe(result, HashSet.has(2)), true)
1324
+ * ```
272
1325
  */
273
1326
  <A>(value: A): (self: HashSet<A>) => HashSet<A>
1327
+
274
1328
  /**
275
- * Removes a value from the `HashSet`.
1329
+ * @example {@link remove} `data-first` API
276
1330
  *
277
- * @since 2.0.0
1331
+ * ```ts
1332
+ * import { HashSet, pipe } from "effect"
1333
+ * import * as assert from "node:assert/strict"
1334
+ *
1335
+ * const set = HashSet.make(0, 1, 2)
1336
+ * const result = HashSet.remove(set, 0)
1337
+ *
1338
+ * assert.equal(HashSet.has(result, 0), false) // it has correctly removed 0
1339
+ * assert.equal(HashSet.has(set, 0), true) // it does not mutate the original set
1340
+ * assert.equal(HashSet.has(result, 1), true)
1341
+ * assert.equal(HashSet.has(result, 2), true)
1342
+ * ```
278
1343
  */
279
1344
  <A>(self: HashSet<A>, value: A): HashSet<A>
280
1345
  } = HS.remove
281
1346
 
282
1347
  /**
283
- * Computes the set difference between this `HashSet` and the specified
284
- * `Iterable<A>`.
1348
+ * Computes the set difference `(A - B)` between this `HashSet` and the
1349
+ * specified `Iterable<A>`.
1350
+ *
1351
+ * Time complexity: **`O(n)`** where n is the number of elements in the set
285
1352
  *
286
1353
  * **NOTE**: the hash and equal of the values in both the set and the iterable
287
- * must be the same.
1354
+ * must be the same; meaning we cannot compute a difference between a `HashSet
1355
+ * of bananas` and a `HashSet of elephants` as they are not the same type and
1356
+ * won't implement the Equal trait in the same way.
288
1357
  *
1358
+ * @memberof HashSet
289
1359
  * @since 2.0.0
1360
+ * @example **Syntax**
1361
+ *
1362
+ * ```ts
1363
+ * import { HashSet, pipe } from "effect"
1364
+ *
1365
+ * // with data-last, a.k.a. pipeable API
1366
+ * pipe(HashSet.make(1, 2, 3), HashSet.difference(HashSet.make(3, 4, 5)))
1367
+ *
1368
+ * // or piped with the pipe function
1369
+ * HashSet.make(1, 2, 3).pipe(HashSet.difference(HashSet.make(3, 4, 5)))
1370
+ *
1371
+ * // or with data-first API
1372
+ * HashSet.difference(HashSet.make(1, 2, 3), HashSet.make(3, 4, 5))
1373
+ * ```
1374
+ *
1375
+ * @see Other `HashSet` operations are {@link intersection} {@link union}
290
1376
  */
291
1377
  export const difference: {
292
1378
  /**
293
- * Computes the set difference between this `HashSet` and the specified
294
- * `Iterable<A>`.
1379
+ * @example {@link difference} `data-last` a.k.a. `pipeable` API
1380
+ *
1381
+ * ```ts
1382
+ * import { HashSet, pipe } from "effect"
1383
+ * import * as assert from "node:assert/strict"
1384
+ *
1385
+ * // Create two sets with some overlapping elements
1386
+ * const thisSet = HashSet.make(1, 2, 3)
1387
+ * const thatIterable = HashSet.make(3, 4, 5)
295
1388
  *
296
- * **NOTE**: the hash and equal of the values in both the set and the iterable
297
- * must be the same.
1389
+ * // Compute the difference (elements in thisSet that are not in thatIterable)
1390
+ * const result = pipe(thisSet, HashSet.difference(thatIterable))
298
1391
  *
299
- * @since 2.0.0
1392
+ * // The result contains only elements from thisSet that are not in thatIterable
1393
+ * assert.deepStrictEqual(HashSet.toValues(result).sort(), [1, 2])
1394
+ *
1395
+ * // The original sets are unchanged
1396
+ * assert.deepStrictEqual(HashSet.toValues(thisSet).sort(), [1, 2, 3])
1397
+ * assert.deepStrictEqual(
1398
+ * HashSet.toValues(thatIterable).sort(),
1399
+ * [3, 4, 5]
1400
+ * )
1401
+ *
1402
+ * // You can also use arrays or other iterables
1403
+ * const diffWithArray = pipe(thisSet, HashSet.difference([3, 4]))
1404
+ * assert.deepStrictEqual(HashSet.toValues(diffWithArray).sort(), [1, 2])
1405
+ * ```
300
1406
  */
301
1407
  <A>(that: Iterable<A>): (self: HashSet<A>) => HashSet<A>
1408
+
302
1409
  /**
303
- * Computes the set difference between this `HashSet` and the specified
304
- * `Iterable<A>`.
1410
+ * @example {@link difference} `data-first` API
1411
+ *
1412
+ * ```ts
1413
+ * import { HashSet } from "effect"
1414
+ * import * as assert from "node:assert/strict"
1415
+ *
1416
+ * // Create two sets with some overlapping elements
1417
+ * const thisSet = HashSet.make(1, 2, 3)
1418
+ * const thatIterable = HashSet.make(3, 4, 5)
1419
+ *
1420
+ * // Compute the difference using data-first API
1421
+ * const result = HashSet.difference(thisSet, thatIterable)
305
1422
  *
306
- * **NOTE**: the hash and equal of the values in both the set and the iterable
307
- * must be the same.
1423
+ * // The result contains only elements from thisSet that are not in thatIterable
1424
+ * assert.deepStrictEqual(HashSet.toValues(result).sort(), [1, 2])
308
1425
  *
309
- * @since 2.0.0
1426
+ * // The original sets are unchanged
1427
+ * assert.deepStrictEqual(HashSet.toValues(thisSet).sort(), [1, 2, 3])
1428
+ * assert.deepStrictEqual(
1429
+ * HashSet.toValues(thatIterable).sort(),
1430
+ * [3, 4, 5]
1431
+ * )
1432
+ *
1433
+ * // You can also compute the difference in the other direction
1434
+ * const reverseResult = HashSet.difference(thatIterable, thisSet)
1435
+ * assert.deepStrictEqual(HashSet.toValues(reverseResult).sort(), [4, 5])
1436
+ * ```
310
1437
  */
311
1438
  <A>(self: HashSet<A>, that: Iterable<A>): HashSet<A>
312
1439
  } = HS.difference
313
1440
 
314
1441
  /**
315
1442
  * Returns a `HashSet` of values which are present in both this set and that
316
- * `Iterable<A>`.
1443
+ * `Iterable<A>`. Computes set intersection (A ∩ B)
1444
+ *
1445
+ * Time complexity: **`O(n)`** where n is the number of elements in the smaller
1446
+ * set
317
1447
  *
318
1448
  * **NOTE**: the hash and equal of the values in both the set and the iterable
319
1449
  * must be the same.
320
1450
  *
1451
+ * @memberof HashSet
321
1452
  * @since 2.0.0
1453
+ * @example **Syntax**
1454
+ *
1455
+ * ```ts
1456
+ * import { HashSet, pipe } from "effect"
1457
+ *
1458
+ * // with data-last, a.k.a. pipeable API
1459
+ * pipe(HashSet.make(1, 2, 3), HashSet.intersection(HashSet.make(2, 3, 4)))
1460
+ *
1461
+ * // or piped with the pipe function
1462
+ * HashSet.make(1, 2, 3).pipe(HashSet.intersection(HashSet.make(2, 3, 4)))
1463
+ *
1464
+ * // or with data-first API
1465
+ * HashSet.intersection(HashSet.make(1, 2, 3), HashSet.make(2, 3, 4))
1466
+ * ```
1467
+ *
1468
+ * @see Other `HashSet` operations are {@link difference} {@link union}
322
1469
  */
323
1470
  export const intersection: {
324
1471
  /**
325
- * Returns a `HashSet` of values which are present in both this set and that
326
- * `Iterable<A>`.
1472
+ * @example {@link intersection} `data-last` a.k.a. `pipeable` API
1473
+ *
1474
+ * ```ts
1475
+ * import { HashSet, pipe } from "effect"
1476
+ * import * as assert from "node:assert/strict"
1477
+ *
1478
+ * // Create two sets with some overlapping elements
1479
+ * const set1 = HashSet.make(1, 2, 3)
1480
+ * const set2 = HashSet.make(2, 3, 4)
327
1481
  *
328
- * **NOTE**: the hash and equal of the values in both the set and the iterable
329
- * must be the same.
1482
+ * // Compute the intersection (elements that are in both sets)
1483
+ * const result = pipe(set1, HashSet.intersection(set2))
330
1484
  *
331
- * @since 2.0.0
1485
+ * // The result contains only elements that are in both sets
1486
+ * assert.deepStrictEqual(HashSet.toValues(result).sort(), [2, 3])
1487
+ *
1488
+ * // The original sets are unchanged
1489
+ * assert.deepStrictEqual(HashSet.toValues(set1).sort(), [1, 2, 3])
1490
+ * assert.deepStrictEqual(HashSet.toValues(set2).sort(), [2, 3, 4])
1491
+ *
1492
+ * // You can also use arrays or other iterables
1493
+ * const intersectWithArray = pipe(set1, HashSet.intersection([2, 3, 5]))
1494
+ * assert.deepStrictEqual(
1495
+ * HashSet.toValues(intersectWithArray).sort(),
1496
+ * [2, 3]
1497
+ * )
1498
+ * ```
332
1499
  */
333
1500
  <A>(that: Iterable<A>): (self: HashSet<A>) => HashSet<A>
1501
+
334
1502
  /**
335
- * Returns a `HashSet` of values which are present in both this set and that
336
- * `Iterable<A>`.
1503
+ * @example {@link intersection} `data-first` API
337
1504
  *
338
- * **NOTE**: the hash and equal of the values in both the set and the iterable
339
- * must be the same.
1505
+ * ```ts
1506
+ * import { HashSet } from "effect"
1507
+ * import * as assert from "node:assert/strict"
340
1508
  *
341
- * @since 2.0.0
1509
+ * // Create two sets with some overlapping elements
1510
+ * const set1 = HashSet.make(1, 2, 3)
1511
+ * const set2 = HashSet.make(2, 3, 4)
1512
+ *
1513
+ * // Compute the intersection using data-first API
1514
+ * const result = HashSet.intersection(set1, set2)
1515
+ *
1516
+ * // The result contains only elements that are in both sets
1517
+ * assert.deepStrictEqual(HashSet.toValues(result).sort(), [2, 3])
1518
+ *
1519
+ * // The original sets are unchanged
1520
+ * assert.deepStrictEqual(HashSet.toValues(set1).sort(), [1, 2, 3])
1521
+ * assert.deepStrictEqual(HashSet.toValues(set2).sort(), [2, 3, 4])
1522
+ *
1523
+ * // You can also use arrays or other iterables
1524
+ * const intersectWithArray = HashSet.intersection(set1, [2, 3, 5])
1525
+ * assert.deepStrictEqual(
1526
+ * HashSet.toValues(intersectWithArray).sort(),
1527
+ * [2, 3]
1528
+ * )
1529
+ * ```
342
1530
  */
343
1531
  <A>(self: HashSet<A>, that: Iterable<A>): HashSet<A>
344
1532
  } = HS.intersection
345
1533
 
346
1534
  /**
347
- * Computes the set union `(`self` + `that`)` between this `HashSet` and the
1535
+ * Computes the set union `( self that )` between this `HashSet` and the
348
1536
  * specified `Iterable<A>`.
349
1537
  *
1538
+ * Time complexity: **`O(n)`** where n is the number of elements in the set
1539
+ *
350
1540
  * **NOTE**: the hash and equal of the values in both the set and the iterable
351
1541
  * must be the same.
352
1542
  *
1543
+ * @memberof HashSet
353
1544
  * @since 2.0.0
1545
+ * @example **Syntax**
1546
+ *
1547
+ * ```ts
1548
+ * import { HashSet, pipe } from "effect"
1549
+ *
1550
+ * // with data-last, a.k.a. pipeable API
1551
+ * pipe(HashSet.make(1, 2, 3), HashSet.union(HashSet.make(3, 4, 5)))
1552
+ *
1553
+ * // or piped with the pipe function
1554
+ * HashSet.make(1, 2, 3).pipe(HashSet.union(HashSet.make(3, 4, 5)))
1555
+ *
1556
+ * // or with data-first API
1557
+ * HashSet.union(HashSet.make(1, 2, 3), HashSet.make(3, 4, 5))
1558
+ * ```
1559
+ *
1560
+ * @see Other `HashSet` operations are {@link difference} {@link intersection}
354
1561
  */
355
1562
  export const union: {
356
1563
  /**
357
- * Computes the set union `(`self` + `that`)` between this `HashSet` and the
358
- * specified `Iterable<A>`.
1564
+ * @example {@link union} `data-last` a.k.a. `pipeable` API
1565
+ *
1566
+ * ```ts
1567
+ * import { HashSet, pipe } from "effect"
1568
+ * import * as assert from "node:assert/strict"
1569
+ *
1570
+ * // Create two sets with some overlapping elements
1571
+ * const selfSet = HashSet.make(1, 2, 3)
1572
+ * const thatIterable = HashSet.make(3, 4, 5)
359
1573
  *
360
- * **NOTE**: the hash and equal of the values in both the set and the iterable
361
- * must be the same.
1574
+ * // Compute the union (all elements from both sets)
1575
+ * const result = pipe(selfSet, HashSet.union(thatIterable))
362
1576
  *
363
- * @since 2.0.0
1577
+ * // The result contains all elements from both sets (without duplicates)
1578
+ * assert.deepStrictEqual(
1579
+ * HashSet.toValues(result).sort(),
1580
+ * [1, 2, 3, 4, 5]
1581
+ * )
1582
+ *
1583
+ * // The original sets are unchanged
1584
+ * assert.deepStrictEqual(HashSet.toValues(selfSet).sort(), [1, 2, 3])
1585
+ * assert.deepStrictEqual(
1586
+ * HashSet.toValues(thatIterable).sort(),
1587
+ * [3, 4, 5]
1588
+ * )
1589
+ *
1590
+ * // You can also use arrays or other iterables
1591
+ * const unionWithArray = pipe(selfSet, HashSet.union([4, 5, 6]))
1592
+ * assert.deepStrictEqual(
1593
+ * HashSet.toValues(unionWithArray).sort(),
1594
+ * [1, 2, 3, 4, 5, 6]
1595
+ * )
1596
+ * ```
364
1597
  */
365
1598
  <A>(that: Iterable<A>): (self: HashSet<A>) => HashSet<A>
1599
+
366
1600
  /**
367
- * Computes the set union `(`self` + `that`)` between this `HashSet` and the
368
- * specified `Iterable<A>`.
1601
+ * @example {@link union} `data-first` API
1602
+ *
1603
+ * ```ts
1604
+ * import { HashSet } from "effect"
1605
+ * import * as assert from "node:assert/strict"
1606
+ *
1607
+ * // Create two sets with some overlapping elements
1608
+ * const selfSet = HashSet.make(1, 2, 3)
1609
+ * const thatIterable = HashSet.make(3, 4, 5)
1610
+ *
1611
+ * // Compute the union using data-first API
1612
+ * const result = HashSet.union(selfSet, thatIterable)
369
1613
  *
370
- * **NOTE**: the hash and equal of the values in both the set and the iterable
371
- * must be the same.
1614
+ * // The result contains all elements from both sets (without duplicates)
1615
+ * assert.deepStrictEqual(
1616
+ * HashSet.toValues(result).sort(),
1617
+ * [1, 2, 3, 4, 5]
1618
+ * )
372
1619
  *
373
- * @since 2.0.0
1620
+ * // The original sets are unchanged
1621
+ * assert.deepStrictEqual(HashSet.toValues(selfSet).sort(), [1, 2, 3])
1622
+ * assert.deepStrictEqual(
1623
+ * HashSet.toValues(thatIterable).sort(),
1624
+ * [3, 4, 5]
1625
+ * )
1626
+ *
1627
+ * // You can also use arrays or other iterables
1628
+ * const unionWithArray = HashSet.union(selfSet, [4, 5, 6])
1629
+ * assert.deepStrictEqual(
1630
+ * HashSet.toValues(unionWithArray).sort(),
1631
+ * [1, 2, 3, 4, 5, 6]
1632
+ * )
1633
+ * ```
374
1634
  */
375
1635
  <A>(self: HashSet<A>, that: Iterable<A>): HashSet<A>
376
1636
  } = HS.union
@@ -380,23 +1640,83 @@ export const union: {
380
1640
  * will be removed from the `HashSet`, otherwise the value will be added to the
381
1641
  * `HashSet`.
382
1642
  *
1643
+ * Time complexity: **`O(1)`** average
1644
+ *
1645
+ * @memberof HashSet
383
1646
  * @since 2.0.0
1647
+ * @example **Syntax**
1648
+ *
1649
+ * ```ts
1650
+ * import { HashSet, pipe } from "effect"
1651
+ *
1652
+ * // with `data-last`, a.k.a. `pipeable` API
1653
+ * pipe(HashSet.make(0, 1, 2), HashSet.toggle(0))
1654
+ *
1655
+ * // or piped with the pipe function
1656
+ * HashSet.make(0, 1, 2).pipe(HashSet.toggle(0))
1657
+ *
1658
+ * // or with `data-first` API
1659
+ * HashSet.toggle(HashSet.make(0, 1, 2), 0)
1660
+ * ```
1661
+ *
1662
+ * @returns A new `HashSet` where the toggled value is being either added or
1663
+ * removed based on the initial `HashSet` state.
1664
+ * @see Other `HashSet` mutations are {@link add} {@link remove} {@link beginMutation} {@link endMutation} {@link mutate}
384
1665
  */
385
1666
  export const toggle: {
386
1667
  /**
387
- * Checks if a value is present in the `HashSet`. If it is present, the value
388
- * will be removed from the `HashSet`, otherwise the value will be added to the
389
- * `HashSet`.
1668
+ * @example {@link toggle} `data-last` a.k.a. `pipeable` API
1669
+ *
1670
+ * ```ts
1671
+ * import { HashSet, pipe } from "effect"
1672
+ * import assert from "node:assert/strict"
1673
+ *
1674
+ * // arrange
1675
+ * let set = HashSet.make(0, 1, 2)
1676
+ *
1677
+ * // assert 1: 0 is in the set
1678
+ * assert.equal(pipe(set, HashSet.has(0)), true)
1679
+ *
1680
+ * // act 2: toggle 0 once on the set
1681
+ * set = pipe(set, HashSet.toggle(0))
1682
+ *
1683
+ * // assert 2: 0 is not in the set any longer
1684
+ * assert.equal(pipe(set, HashSet.has(0)), false)
390
1685
  *
391
- * @since 2.0.0
1686
+ * // act 3: toggle 0 once again on the set
1687
+ * set = pipe(set, HashSet.toggle(0))
1688
+ *
1689
+ * // assert 3: 0 in now back in the set
1690
+ * assert.equal(pipe(set, HashSet.has(0)), true)
1691
+ * ```
392
1692
  */
393
1693
  <A>(value: A): (self: HashSet<A>) => HashSet<A>
1694
+
394
1695
  /**
395
- * Checks if a value is present in the `HashSet`. If it is present, the value
396
- * will be removed from the `HashSet`, otherwise the value will be added to the
397
- * `HashSet`.
1696
+ * @example {@link toggle} `data-first` API
1697
+ *
1698
+ * ```ts
1699
+ * import { HashSet, pipe } from "effect"
1700
+ * import assert from "node:assert/strict"
1701
+ *
1702
+ * // arrange
1703
+ * let set = HashSet.make(0, 1, 2)
1704
+ *
1705
+ * // assert 1: 0 is in the set
1706
+ * assert.equal(HashSet.has(set, 0), true)
1707
+ *
1708
+ * // act 2: toggle 0 once on the set
1709
+ * set = HashSet.toggle(set, 0)
398
1710
  *
399
- * @since 2.0.0
1711
+ * // assert 2: 0 is not in the set any longer
1712
+ * assert.equal(HashSet.has(set, 0), false)
1713
+ *
1714
+ * // act 3: toggle 0 once again on the set
1715
+ * set = HashSet.toggle(set, 0)
1716
+ *
1717
+ * // assert 3: 0 in now back in the set
1718
+ * assert.equal(HashSet.has(set, 0), true)
1719
+ * ```
400
1720
  */
401
1721
  <A>(self: HashSet<A>, value: A): HashSet<A>
402
1722
  } = HS.toggle
@@ -404,22 +1724,63 @@ export const toggle: {
404
1724
  /**
405
1725
  * Maps over the values of the `HashSet` using the specified function.
406
1726
  *
1727
+ * The time complexity is of **`O(n)`**.
1728
+ *
1729
+ * @memberof HashSet
407
1730
  * @since 2.0.0
408
1731
  * @category mapping
1732
+ * @example **Syntax**
1733
+ *
1734
+ * ```ts
1735
+ * import { HashSet, pipe } from "effect"
1736
+ *
1737
+ * // with `data-last`, a.k.a. `pipeable` API
1738
+ * pipe(
1739
+ * HashSet.make(0, 1, 2), // HashSet.HashSet<number>
1740
+ * HashSet.map(String) // HashSet.HashSet<string>
1741
+ * )
1742
+ *
1743
+ * // or piped with the pipe method
1744
+ * HashSet.make(0, 1, 2).pipe(HashSet.map(String))
1745
+ *
1746
+ * // or with `data-first` API
1747
+ * HashSet.map(HashSet.make(0, 1, 2), String)
1748
+ * ```
409
1749
  */
410
1750
  export const map: {
411
1751
  /**
412
- * Maps over the values of the `HashSet` using the specified function.
1752
+ * @example
1753
+ *
1754
+ * ```ts
1755
+ * import { HashSet, pipe } from "effect"
1756
+ * import * as assert from "node:assert/strict"
413
1757
  *
414
- * @since 2.0.0
415
- * @category mapping
1758
+ * assert.deepStrictEqual(
1759
+ * pipe(
1760
+ * HashSet.make(0, 1, 2), // HashSet.HashSet<number>
1761
+ * HashSet.map((n) => String(n + 1)) // HashSet.HashSet<String>
1762
+ * ),
1763
+ * HashSet.make("1", "2", "3")
1764
+ * )
1765
+ * ```
416
1766
  */
417
1767
  <A, B>(f: (a: A) => B): (self: HashSet<A>) => HashSet<B>
1768
+
418
1769
  /**
419
- * Maps over the values of the `HashSet` using the specified function.
1770
+ * @example
420
1771
  *
421
- * @since 2.0.0
422
- * @category mapping
1772
+ * ```ts
1773
+ * import { HashSet, pipe } from "effect"
1774
+ * import * as assert from "node:assert/strict"
1775
+ *
1776
+ * assert.deepStrictEqual(
1777
+ * HashSet.map(
1778
+ * HashSet.make(0, 1, 2), // HashSet.HashSet<number>
1779
+ * (n) => String(n + 1)
1780
+ * ), // HashSet.HashSet<String>
1781
+ * HashSet.make("1", "2", "3")
1782
+ * )
1783
+ * ```
423
1784
  */
424
1785
  <A, B>(self: HashSet<A>, f: (a: A) => B): HashSet<B>
425
1786
  } = HS.map
@@ -427,22 +1788,65 @@ export const map: {
427
1788
  /**
428
1789
  * Chains over the values of the `HashSet` using the specified function.
429
1790
  *
1791
+ * The time complexity is of **`O(n)`**.
1792
+ *
1793
+ * @memberof HashSet
430
1794
  * @since 2.0.0
431
1795
  * @category sequencing
1796
+ * @example **Syntax**
1797
+ *
1798
+ * ```ts
1799
+ * import { HashSet, pipe } from "effect"
1800
+ *
1801
+ * // with `data-last`, a.k.a. `pipeable` API
1802
+ * pipe(
1803
+ * HashSet.make(0, 1, 2), // HashSet.HashSet<number>
1804
+ * HashSet.flatMap((n) => Array.of(String(n))) // HashSet.HashSet<string>
1805
+ * )
1806
+ *
1807
+ * // or piped with the pipe method
1808
+ * HashSet.make(0, 1, 2) // HashSet.HashSet<number>
1809
+ * .pipe(
1810
+ * HashSet.flatMap((n) => Array.of(String(n))) // HashSet.HashSet<string>
1811
+ * )
1812
+ *
1813
+ * // or with `data-first` API
1814
+ * HashSet.flatMap(HashSet.make(0, 1, 2), (n) => Array.of(String(n)))
1815
+ * ```
432
1816
  */
433
1817
  export const flatMap: {
434
1818
  /**
435
- * Chains over the values of the `HashSet` using the specified function.
1819
+ * @example
436
1820
  *
437
- * @since 2.0.0
438
- * @category sequencing
1821
+ * ```ts
1822
+ * import { HashSet, pipe, List } from "effect"
1823
+ * import * as assert from "node:assert/strict"
1824
+ *
1825
+ * assert.deepStrictEqual(
1826
+ * pipe(
1827
+ * HashSet.make(0, 1, 2),
1828
+ * HashSet.flatMap((n) => List.of(String(n * n))) // needs to return an Iterable
1829
+ * ),
1830
+ * HashSet.make("0", "1", "4")
1831
+ * )
1832
+ * ```
439
1833
  */
440
1834
  <A, B>(f: (a: A) => Iterable<B>): (self: HashSet<A>) => HashSet<B>
1835
+
441
1836
  /**
442
- * Chains over the values of the `HashSet` using the specified function.
1837
+ * @example
1838
+ *
1839
+ * ```ts
1840
+ * import { HashSet, pipe, List } from "effect"
1841
+ * import * as assert from "node:assert/strict"
443
1842
  *
444
- * @since 2.0.0
445
- * @category sequencing
1843
+ * assert.deepStrictEqual(
1844
+ * HashSet.flatMap(HashSet.make(0, 1, 2), (n) =>
1845
+ * List.of(String(n * n * n))
1846
+ * ), // needs to return an Iterable
1847
+ * HashSet.make("0", "1", "8")
1848
+ * )
1849
+ * ```
446
1850
  */
447
1851
  <A, B>(self: HashSet<A>, f: (a: A) => Iterable<B>): HashSet<B>
448
1852
  } = HS.flatMap
@@ -450,22 +1854,63 @@ export const flatMap: {
450
1854
  /**
451
1855
  * Applies the specified function to the values of the `HashSet`.
452
1856
  *
1857
+ * The time complexity is of **`O(n)`**.
1858
+ *
1859
+ * @memberof HashSet
453
1860
  * @since 2.0.0
454
1861
  * @category traversing
1862
+ * @example **Syntax**
1863
+ *
1864
+ * ```ts
1865
+ * import { HashSet, pipe } from "effect"
1866
+ *
1867
+ * // with `data-last`, a.k.a. `pipeable` API
1868
+ * pipe(HashSet.make(0, 1, 2), HashSet.forEach(console.log)) // logs: 0 1 2
1869
+ *
1870
+ * // or piped with the pipe method
1871
+ * HashSet.make(0, 1, 2).pipe(HashSet.forEach(console.log)) // logs: 0 1 2
1872
+ *
1873
+ * // or with `data-first` API
1874
+ * HashSet.forEach(HashSet.make(0, 1, 2), console.log) // logs: 0 1 2
1875
+ * ```
455
1876
  */
456
1877
  export const forEach: {
457
1878
  /**
458
- * Applies the specified function to the values of the `HashSet`.
1879
+ * @example
1880
+ *
1881
+ * ```ts
1882
+ * import { HashSet, pipe } from "effect"
1883
+ * import * as assert from "node:assert/strict"
459
1884
  *
460
- * @since 2.0.0
461
- * @category traversing
1885
+ * const result: Array<number> = []
1886
+ *
1887
+ * pipe(
1888
+ * HashSet.make(0, 1, 2),
1889
+ * HashSet.forEach((n): void => {
1890
+ * result.push(n)
1891
+ * })
1892
+ * )
1893
+ *
1894
+ * assert.deepStrictEqual(result, [0, 1, 2])
1895
+ * ```
462
1896
  */
463
1897
  <A>(f: (value: A) => void): (self: HashSet<A>) => void
1898
+
464
1899
  /**
465
- * Applies the specified function to the values of the `HashSet`.
1900
+ * @example
1901
+ *
1902
+ * ```ts
1903
+ * import { HashSet, pipe } from "effect"
1904
+ * import * as assert from "node:assert/strict"
1905
+ *
1906
+ * const result: Array<number> = []
1907
+ *
1908
+ * HashSet.forEach(HashSet.make(0, 1, 2), (n): void => {
1909
+ * result.push(n)
1910
+ * })
466
1911
  *
467
- * @since 2.0.0
468
- * @category traversing
1912
+ * assert.deepStrictEqual(result, [0, 1, 2])
1913
+ * ```
469
1914
  */
470
1915
  <A>(self: HashSet<A>, f: (value: A) => void): void
471
1916
  } = HS.forEach
@@ -473,22 +1918,63 @@ export const forEach: {
473
1918
  /**
474
1919
  * Reduces the specified state over the values of the `HashSet`.
475
1920
  *
1921
+ * The time complexity is of **`O(n)`**.
1922
+ *
1923
+ * @memberof HashSet
476
1924
  * @since 2.0.0
477
1925
  * @category folding
1926
+ * @example **Syntax**
1927
+ *
1928
+ * ```ts
1929
+ * import { HashSet, pipe } from "effect"
1930
+ *
1931
+ * const sum = (a: number, b: number): number => a + b
1932
+ *
1933
+ * // with `data-last`, a.k.a. `pipeable` API
1934
+ * pipe(HashSet.make(0, 1, 2), HashSet.reduce(0, sum))
1935
+ *
1936
+ * // or with the pipe method
1937
+ * HashSet.make(0, 1, 2).pipe(HashSet.reduce(0, sum))
1938
+ *
1939
+ * // or with `data-first` API
1940
+ * HashSet.reduce(HashSet.make(0, 1, 2), 0, sum)
1941
+ * ```
478
1942
  */
479
1943
  export const reduce: {
480
1944
  /**
481
- * Reduces the specified state over the values of the `HashSet`.
1945
+ * @example
482
1946
  *
483
- * @since 2.0.0
484
- * @category folding
1947
+ * ```ts
1948
+ * import { HashSet, pipe } from "effect"
1949
+ * import * as assert from "node:assert/strict"
1950
+ *
1951
+ * assert.equal(
1952
+ * pipe(
1953
+ * HashSet.make(0, 1, 2),
1954
+ * HashSet.reduce(10, (accumulator, value) => accumulator + value)
1955
+ * ),
1956
+ * 13
1957
+ * )
1958
+ * ```
485
1959
  */
486
1960
  <A, Z>(zero: Z, f: (accumulator: Z, value: A) => Z): (self: HashSet<A>) => Z
1961
+
487
1962
  /**
488
- * Reduces the specified state over the values of the `HashSet`.
1963
+ * @example
1964
+ *
1965
+ * ```ts
1966
+ * import { HashSet } from "effect"
1967
+ * import * as assert from "node:assert/strict"
489
1968
  *
490
- * @since 2.0.0
491
- * @category folding
1969
+ * assert.equal(
1970
+ * HashSet.reduce(
1971
+ * HashSet.make(0, 1, 2),
1972
+ * -3,
1973
+ * (accumulator, value) => accumulator + value
1974
+ * ),
1975
+ * 0
1976
+ * )
1977
+ * ```
492
1978
  */
493
1979
  <A, Z>(self: HashSet<A>, zero: Z, f: (accumulator: Z, value: A) => Z): Z
494
1980
  } = HS.reduce
@@ -496,36 +1982,149 @@ export const reduce: {
496
1982
  /**
497
1983
  * Filters values out of a `HashSet` using the specified predicate.
498
1984
  *
1985
+ * The time complexity is of **`O(n)`**.
1986
+ *
1987
+ * @memberof HashSet
499
1988
  * @since 2.0.0
500
1989
  * @category filtering
1990
+ * @example **Syntax** with {@link Predicate}
1991
+ *
1992
+ * ```ts
1993
+ * import { HashSet, type Predicate, pipe } from "effect"
1994
+ *
1995
+ * const filterPositiveNumbers: Predicate.Predicate<number> = (n) => n > 0
1996
+ *
1997
+ * // with `data-last`, a.k.a. `pipeable` API
1998
+ * pipe(
1999
+ * HashSet.make(-2, -1, 0, 1, 2),
2000
+ * HashSet.filter(filterPositiveNumbers)
2001
+ * )
2002
+ *
2003
+ * // or with the pipe method
2004
+ * HashSet.make(-2, -1, 0, 1, 2).pipe(HashSet.filter(filterPositiveNumbers))
2005
+ *
2006
+ * // or with `data-first` API
2007
+ * HashSet.filter(HashSet.make(-2, -1, 0, 1, 2), filterPositiveNumbers)
2008
+ * ```
2009
+ *
2010
+ * @example **Syntax** with {@link Refinement}
2011
+ *
2012
+ * ```ts
2013
+ * import { HashSet, pipe } from "effect"
2014
+ *
2015
+ * const stringRefinement = (value: unknown): value is string =>
2016
+ * typeof value === "string"
2017
+ *
2018
+ * // with `data-last`, a.k.a. `pipeable` API
2019
+ * pipe(
2020
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier"), // // HashSet.HashSet<number | string>
2021
+ * HashSet.filter(stringRefinement)
2022
+ * ) // HashSet.HashSet<string>
2023
+ *
2024
+ * // or with the pipe method
2025
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier") // HashSet.HashSet<number | string>
2026
+ * .pipe(HashSet.filter(stringRefinement)) // HashSet.HashSet<string>
2027
+ *
2028
+ * // or with `data-first` API
2029
+ * HashSet.filter(
2030
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier"), // HashSet.HashSet<number | string>
2031
+ * stringRefinement
2032
+ * ) // HashSet.HashSet<string>
2033
+ * ```
501
2034
  */
502
2035
  export const filter: {
503
2036
  /**
504
- * Filters values out of a `HashSet` using the specified predicate.
2037
+ * @example
2038
+ *
2039
+ * ```ts
2040
+ * import { HashSet, pipe, Predicate } from "effect"
2041
+ * import * as assert from "node:assert/strict"
2042
+ *
2043
+ * const numbersAndStringsHashSet: HashSet.HashSet<number | string> =
2044
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier")
2045
+ *
2046
+ * const stringRefinement: Predicate.Refinement<
2047
+ * string | number,
2048
+ * string
2049
+ * > = (value) => typeof value === "string"
505
2050
  *
506
- * @since 2.0.0
507
- * @category filtering
2051
+ * const stringHashSet: HashSet.HashSet<string> = pipe(
2052
+ * numbersAndStringsHashSet,
2053
+ * HashSet.filter(stringRefinement)
2054
+ * )
2055
+ *
2056
+ * assert.equal(
2057
+ * pipe(stringHashSet, HashSet.every(Predicate.isString)),
2058
+ * true
2059
+ * )
2060
+ * ```
508
2061
  */
509
- <A, B extends A>(refinement: Refinement<NoInfer<A>, B>): (self: HashSet<A>) => HashSet<B>
2062
+ <A, B extends A>(
2063
+ refinement: Refinement<NoInfer<A>, B>
2064
+ ): (self: HashSet<A>) => HashSet<B>
2065
+
510
2066
  /**
511
- * Filters values out of a `HashSet` using the specified predicate.
2067
+ * @example
2068
+ *
2069
+ * ```ts
2070
+ * import { HashSet, pipe, type Predicate } from "effect"
2071
+ * import * as assert from "node:assert/strict"
512
2072
  *
513
- * @since 2.0.0
514
- * @category filtering
2073
+ * const filterPositiveNumbers: Predicate.Predicate<number> = (n) => n > 0
2074
+ *
2075
+ * assert.deepStrictEqual(
2076
+ * pipe(
2077
+ * HashSet.make(-2, -1, 0, 1, 2),
2078
+ * HashSet.filter(filterPositiveNumbers)
2079
+ * ),
2080
+ * HashSet.make(1, 2)
2081
+ * )
2082
+ * ```
515
2083
  */
516
2084
  <A>(predicate: Predicate<NoInfer<A>>): (self: HashSet<A>) => HashSet<A>
2085
+
517
2086
  /**
518
- * Filters values out of a `HashSet` using the specified predicate.
2087
+ * @example
2088
+ *
2089
+ * ```ts
2090
+ * import { HashSet, Predicate } from "effect"
2091
+ * import * as assert from "node:assert/strict"
519
2092
  *
520
- * @since 2.0.0
521
- * @category filtering
2093
+ * const numbersAndStringsHashSet: HashSet.HashSet<number | string> =
2094
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier")
2095
+ *
2096
+ * const stringRefinement: Predicate.Refinement<
2097
+ * string | number,
2098
+ * string
2099
+ * > = (value) => typeof value === "string"
2100
+ *
2101
+ * const stringHashSet: HashSet.HashSet<string> = HashSet.filter(
2102
+ * numbersAndStringsHashSet,
2103
+ * stringRefinement
2104
+ * )
2105
+ *
2106
+ * assert.equal(HashSet.every(stringHashSet, Predicate.isString), true)
2107
+ * ```
522
2108
  */
523
- <A, B extends A>(self: HashSet<A>, refinement: Refinement<A, B>): HashSet<B>
2109
+ <A, B extends A>(
2110
+ self: HashSet<A>,
2111
+ refinement: Refinement<A, B>
2112
+ ): HashSet<B>
2113
+
524
2114
  /**
525
- * Filters values out of a `HashSet` using the specified predicate.
2115
+ * @example
2116
+ *
2117
+ * ```ts
2118
+ * import { HashSet, pipe, type Predicate } from "effect"
2119
+ * import * as assert from "node:assert/strict"
2120
+ *
2121
+ * const filterPositiveNumbers: Predicate.Predicate<number> = (n) => n > 0
526
2122
  *
527
- * @since 2.0.0
528
- * @category filtering
2123
+ * assert.deepStrictEqual(
2124
+ * HashSet.filter(HashSet.make(-2, -1, 0, 1, 2), filterPositiveNumbers),
2125
+ * HashSet.make(1, 2)
2126
+ * )
2127
+ * ```
529
2128
  */
530
2129
  <A>(self: HashSet<A>, predicate: Predicate<A>): HashSet<A>
531
2130
  } = HS.filter
@@ -537,52 +2136,168 @@ export const filter: {
537
2136
  * right side of the resulting `Tuple`, otherwise the value will be placed into
538
2137
  * the left side.
539
2138
  *
2139
+ * Time complexity is of **`O(n)`**.
2140
+ *
2141
+ * @memberof HashSet
540
2142
  * @since 2.0.0
541
2143
  * @category partitioning
2144
+ * @example **Syntax** with {@link Predicate}
2145
+ *
2146
+ * ```ts
2147
+ * import { HashSet, pipe, Predicate } from "effect"
2148
+ *
2149
+ * // with `data-last`, a.k.a. `pipeable` API
2150
+ * pipe(
2151
+ * HashSet.make(0, 1, 2, 3, 4, 5),
2152
+ * HashSet.partition((n) => n % 2 === 0)
2153
+ * )
2154
+ *
2155
+ * // or with the pipe method
2156
+ * HashSet.make(0, 1, 2, 3, 4, 5).pipe(
2157
+ * HashSet.partition((n) => n % 2 === 0)
2158
+ * )
2159
+ *
2160
+ * // or with `data-first` API
2161
+ * HashSet.partition(HashSet.make(0, 1, 2, 3, 4, 5), (n) => n % 2 === 0)
2162
+ * ```
2163
+ *
2164
+ * @example **Syntax** with {@link Refinement}
2165
+ *
2166
+ * ```ts
2167
+ * import { HashSet, pipe, Predicate } from "effect"
2168
+ *
2169
+ * const stringRefinement: Predicate.Refinement<string | number, string> = (
2170
+ * value
2171
+ * ) => typeof value === "string"
2172
+ *
2173
+ * // with `data-last`, a.k.a. `pipeable` API
2174
+ * pipe(
2175
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier"),
2176
+ * HashSet.partition(stringRefinement)
2177
+ * )
2178
+ *
2179
+ * // or with the pipe method
2180
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier").pipe(
2181
+ * HashSet.partition(stringRefinement)
2182
+ * )
2183
+ *
2184
+ * // or with `data-first` API
2185
+ * HashSet.partition(
2186
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier"),
2187
+ * stringRefinement
2188
+ * )
2189
+ * ```
542
2190
  */
543
2191
  export const partition: {
544
2192
  /**
545
- * Partition the values of a `HashSet` using the specified predicate.
2193
+ * @example
2194
+ *
2195
+ * ```ts
2196
+ * import { HashSet, pipe, Predicate } from "effect"
2197
+ * import * as assert from "node:assert/strict"
546
2198
  *
547
- * If a value matches the predicate, it will be placed into the `HashSet` on the
548
- * right side of the resulting `Tuple`, otherwise the value will be placed into
549
- * the left side.
2199
+ * const numbersAndStringsHashSet: HashSet.HashSet<number | string> =
2200
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier")
550
2201
  *
551
- * @since 2.0.0
552
- * @category partitioning
2202
+ * const stringRefinement: Predicate.Refinement<
2203
+ * string | number,
2204
+ * string
2205
+ * > = (value) => typeof value === "string"
2206
+ *
2207
+ * const [
2208
+ * excluded, // HashSet.HashSet<number>
2209
+ * satisfying // HashSet.HashSet<string>
2210
+ * ] = pipe(numbersAndStringsHashSet, HashSet.partition(stringRefinement))
2211
+ *
2212
+ * assert.equal(pipe(satisfying, HashSet.every(Predicate.isString)), true)
2213
+ * assert.equal(pipe(excluded, HashSet.every(Predicate.isNumber)), true)
2214
+ *
2215
+ * assert.deepStrictEqual(excluded, HashSet.make(1, 2, 3, 4))
2216
+ * assert.deepStrictEqual(
2217
+ * satisfying,
2218
+ * HashSet.make("unos", "two", "trois", "vier")
2219
+ * )
2220
+ * ```
553
2221
  */
554
- <A, B extends A>(refinement: Refinement<NoInfer<A>, B>): (self: HashSet<A>) => [excluded: HashSet<Exclude<A, B>>, satisfying: HashSet<B>]
2222
+ <A, B extends A>(
2223
+ refinement: Refinement<NoInfer<A>, B>
2224
+ ): (
2225
+ self: HashSet<A>
2226
+ ) => [excluded: HashSet<Exclude<A, B>>, satisfying: HashSet<B>]
2227
+
555
2228
  /**
556
- * Partition the values of a `HashSet` using the specified predicate.
2229
+ * @example
2230
+ *
2231
+ * ```ts
2232
+ * import { HashSet, pipe } from "effect"
2233
+ * import * as assert from "node:assert/strict"
557
2234
  *
558
- * If a value matches the predicate, it will be placed into the `HashSet` on the
559
- * right side of the resulting `Tuple`, otherwise the value will be placed into
560
- * the left side.
2235
+ * const [excluded, satisfying] = pipe(
2236
+ * HashSet.make(0, 1, 2, 3, 4, 5),
2237
+ * HashSet.partition((n) => n % 2 === 0)
2238
+ * )
561
2239
  *
562
- * @since 2.0.0
563
- * @category partitioning
2240
+ * assert.deepStrictEqual(excluded, HashSet.make(1, 3, 5))
2241
+ * assert.deepStrictEqual(satisfying, HashSet.make(0, 2, 4))
2242
+ * ```
564
2243
  */
565
- <A>(predicate: Predicate<NoInfer<A>>): (self: HashSet<A>) => [excluded: HashSet<A>, satisfying: HashSet<A>]
2244
+ <A>(
2245
+ predicate: Predicate<NoInfer<A>>
2246
+ ): (self: HashSet<A>) => [excluded: HashSet<A>, satisfying: HashSet<A>]
2247
+
566
2248
  /**
567
- * Partition the values of a `HashSet` using the specified predicate.
2249
+ * @example
568
2250
  *
569
- * If a value matches the predicate, it will be placed into the `HashSet` on the
570
- * right side of the resulting `Tuple`, otherwise the value will be placed into
571
- * the left side.
2251
+ * ```ts
2252
+ * import { HashSet, pipe, Predicate } from "effect"
2253
+ * import * as assert from "node:assert/strict"
572
2254
  *
573
- * @since 2.0.0
574
- * @category partitioning
2255
+ * const numbersAndStringsHashSet: HashSet.HashSet<number | string> =
2256
+ * HashSet.make(1, "unos", 2, "two", 3, "trois", 4, "vier")
2257
+ *
2258
+ * const stringRefinement: Predicate.Refinement<
2259
+ * string | number,
2260
+ * string
2261
+ * > = (value) => typeof value === "string"
2262
+ *
2263
+ * const [
2264
+ * excluded, // HashSet.HashSet<number>
2265
+ * satisfying // HashSet.HashSet<string>
2266
+ * ] = HashSet.partition(numbersAndStringsHashSet, stringRefinement)
2267
+ *
2268
+ * assert.equal(HashSet.every(satisfying, Predicate.isString), true)
2269
+ * assert.equal(HashSet.every(excluded, Predicate.isNumber), true)
2270
+ *
2271
+ * assert.deepStrictEqual(excluded, HashSet.make(1, 2, 3, 4))
2272
+ * assert.deepStrictEqual(
2273
+ * satisfying,
2274
+ * HashSet.make("unos", "two", "trois", "vier")
2275
+ * )
2276
+ * ```
575
2277
  */
576
- <A, B extends A>(self: HashSet<A>, refinement: Refinement<A, B>): [excluded: HashSet<Exclude<A, B>>, satisfying: HashSet<B>]
2278
+ <A, B extends A>(
2279
+ self: HashSet<A>,
2280
+ refinement: Refinement<A, B>
2281
+ ): [excluded: HashSet<Exclude<A, B>>, satisfying: HashSet<B>]
2282
+
577
2283
  /**
578
- * Partition the values of a `HashSet` using the specified predicate.
2284
+ * @example
2285
+ *
2286
+ * ```ts
2287
+ * import { HashSet } from "effect"
2288
+ * import * as assert from "node:assert/strict"
579
2289
  *
580
- * If a value matches the predicate, it will be placed into the `HashSet` on the
581
- * right side of the resulting `Tuple`, otherwise the value will be placed into
582
- * the left side.
2290
+ * const [excluded, satisfying] = HashSet.partition(
2291
+ * HashSet.make(0, 1, 2, 3, 4, 5),
2292
+ * (n) => n % 2 === 0
2293
+ * )
583
2294
  *
584
- * @since 2.0.0
585
- * @category partitioning
2295
+ * assert.deepStrictEqual(excluded, HashSet.make(1, 3, 5))
2296
+ * assert.deepStrictEqual(satisfying, HashSet.make(0, 2, 4))
2297
+ * ```
586
2298
  */
587
- <A>(self: HashSet<A>, predicate: Predicate<A>): [excluded: HashSet<A>, satisfying: HashSet<A>]
2299
+ <A>(
2300
+ self: HashSet<A>,
2301
+ predicate: Predicate<A>
2302
+ ): [excluded: HashSet<A>, satisfying: HashSet<A>]
588
2303
  } = HS.partition