effect 3.14.2 → 3.14.4

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