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/dist/cjs/Effect.js +1 -1
- package/dist/cjs/Function.js +33 -12
- package/dist/cjs/Function.js.map +1 -1
- package/dist/cjs/HashSet.js +1038 -7
- package/dist/cjs/HashSet.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/dts/Data.d.ts +4 -4
- package/dist/dts/Data.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +1 -1
- package/dist/dts/Function.d.ts +99 -36
- package/dist/dts/Function.d.ts.map +1 -1
- package/dist/dts/HashSet.d.ts +1824 -155
- package/dist/dts/HashSet.d.ts.map +1 -1
- package/dist/dts/index.d.ts +250 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/Effect.js +1 -1
- package/dist/esm/Function.js +33 -12
- package/dist/esm/Function.js.map +1 -1
- package/dist/esm/HashSet.js +1038 -7
- package/dist/esm/HashSet.js.map +1 -1
- package/dist/esm/index.js +250 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/package.json +1 -1
- package/src/Data.ts +4 -4
- package/src/Effect.ts +1 -1
- package/src/Function.ts +99 -36
- package/src/HashSet.ts +1878 -163
- package/src/index.ts +250 -0
- package/src/internal/version.ts +1 -1
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
|
-
*
|
|
35
|
-
*
|
|
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
|
-
*
|
|
40
|
-
*
|
|
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
|
-
*
|
|
584
|
+
* @example {@link has} `data-last` a.k.a. `pipeable` API
|
|
78
585
|
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
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
|
-
*
|
|
601
|
+
* @example {@link has} `data-first` API
|
|
85
602
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
103
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
110
|
-
*
|
|
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
|
-
*
|
|
759
|
+
* @example
|
|
760
|
+
*
|
|
761
|
+
* ```ts
|
|
762
|
+
* import * as assert from "node:assert/strict"
|
|
763
|
+
* import { Effect, HashSet, pipe, Predicate } from "effect"
|
|
124
764
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
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>(
|
|
781
|
+
<A, B extends A>(
|
|
782
|
+
refinement: Refinement<NoInfer<A>, B>
|
|
783
|
+
): (self: HashSet<A>) => self is HashSet<B>
|
|
784
|
+
|
|
129
785
|
/**
|
|
130
|
-
*
|
|
786
|
+
* @example
|
|
787
|
+
*
|
|
788
|
+
* ```ts
|
|
789
|
+
* import * as assert from "node:assert/strict"
|
|
790
|
+
* import { HashSet, pipe } from "effect"
|
|
131
791
|
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
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
|
-
*
|
|
806
|
+
* @example
|
|
807
|
+
*
|
|
808
|
+
* ```ts
|
|
809
|
+
* import * as assert from "node:assert/strict"
|
|
810
|
+
* import { Effect, HashSet, pipe, Predicate } from "effect"
|
|
138
811
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
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>(
|
|
828
|
+
<A, B extends A>(
|
|
829
|
+
self: HashSet<A>,
|
|
830
|
+
refinement: Refinement<A, B>
|
|
831
|
+
): self is HashSet<B>
|
|
832
|
+
|
|
143
833
|
/**
|
|
144
|
-
*
|
|
834
|
+
* @example
|
|
835
|
+
*
|
|
836
|
+
* ```ts
|
|
837
|
+
* import * as assert from "node:assert/strict"
|
|
838
|
+
* import { HashSet } from "effect"
|
|
145
839
|
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
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
|
-
*
|
|
164
|
-
*
|
|
888
|
+
* @example
|
|
889
|
+
*
|
|
890
|
+
* ```ts
|
|
891
|
+
* import { HashSet, pipe } from "effect"
|
|
892
|
+
* import * as assert from "node:assert/strict"
|
|
165
893
|
*
|
|
166
|
-
*
|
|
894
|
+
* assert.equal(
|
|
895
|
+
* pipe(
|
|
896
|
+
* HashSet.make(0, 1), //
|
|
897
|
+
* HashSet.isSubset(HashSet.make(1, 2))
|
|
898
|
+
* ),
|
|
899
|
+
* false
|
|
900
|
+
* )
|
|
167
901
|
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
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
|
-
*
|
|
174
|
-
*
|
|
914
|
+
* @example
|
|
915
|
+
*
|
|
916
|
+
* ```ts
|
|
917
|
+
* import { HashSet } from "effect"
|
|
918
|
+
* import * as assert from "node:assert/strict"
|
|
175
919
|
*
|
|
176
|
-
*
|
|
920
|
+
* assert.equal(HashSet.isSubset(set1, set2), false)
|
|
177
921
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
1146
|
+
* @example {@linkcode HashSet.mutate} `data-last` a.k.a. `pipeable` API
|
|
230
1147
|
*
|
|
231
|
-
*
|
|
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
|
-
*
|
|
1182
|
+
* @example {@linkcode HashSet.mutate} `data-first` API
|
|
236
1183
|
*
|
|
237
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
1311
|
+
* @example {@link remove} `data-last` a.k.a. `pipeable` API
|
|
270
1312
|
*
|
|
271
|
-
*
|
|
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
|
-
*
|
|
1329
|
+
* @example {@link remove} `data-first` API
|
|
276
1330
|
*
|
|
277
|
-
*
|
|
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
|
|
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
|
-
*
|
|
294
|
-
*
|
|
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
|
-
*
|
|
297
|
-
*
|
|
1389
|
+
* // Compute the difference (elements in thisSet that are not in thatIterable)
|
|
1390
|
+
* const result = pipe(thisSet, HashSet.difference(thatIterable))
|
|
298
1391
|
*
|
|
299
|
-
*
|
|
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
|
-
*
|
|
304
|
-
*
|
|
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
|
-
*
|
|
307
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
326
|
-
*
|
|
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
|
-
*
|
|
329
|
-
*
|
|
1482
|
+
* // Compute the intersection (elements that are in both sets)
|
|
1483
|
+
* const result = pipe(set1, HashSet.intersection(set2))
|
|
330
1484
|
*
|
|
331
|
-
*
|
|
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
|
-
*
|
|
336
|
-
* `Iterable<A>`.
|
|
1503
|
+
* @example {@link intersection} `data-first` API
|
|
337
1504
|
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
1505
|
+
* ```ts
|
|
1506
|
+
* import { HashSet } from "effect"
|
|
1507
|
+
* import * as assert from "node:assert/strict"
|
|
340
1508
|
*
|
|
341
|
-
*
|
|
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 `(
|
|
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
|
-
*
|
|
358
|
-
*
|
|
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
|
-
*
|
|
361
|
-
*
|
|
1574
|
+
* // Compute the union (all elements from both sets)
|
|
1575
|
+
* const result = pipe(selfSet, HashSet.union(thatIterable))
|
|
362
1576
|
*
|
|
363
|
-
*
|
|
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
|
-
*
|
|
368
|
-
*
|
|
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
|
-
*
|
|
371
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
1752
|
+
* @example
|
|
1753
|
+
*
|
|
1754
|
+
* ```ts
|
|
1755
|
+
* import { HashSet, pipe } from "effect"
|
|
1756
|
+
* import * as assert from "node:assert/strict"
|
|
413
1757
|
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
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
|
-
*
|
|
1770
|
+
* @example
|
|
420
1771
|
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
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
|
-
*
|
|
1819
|
+
* @example
|
|
436
1820
|
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
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
|
-
*
|
|
1837
|
+
* @example
|
|
1838
|
+
*
|
|
1839
|
+
* ```ts
|
|
1840
|
+
* import { HashSet, pipe, List } from "effect"
|
|
1841
|
+
* import * as assert from "node:assert/strict"
|
|
443
1842
|
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
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
|
-
*
|
|
1879
|
+
* @example
|
|
1880
|
+
*
|
|
1881
|
+
* ```ts
|
|
1882
|
+
* import { HashSet, pipe } from "effect"
|
|
1883
|
+
* import * as assert from "node:assert/strict"
|
|
459
1884
|
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
468
|
-
*
|
|
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
|
-
*
|
|
1945
|
+
* @example
|
|
482
1946
|
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
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
|
-
*
|
|
1963
|
+
* @example
|
|
1964
|
+
*
|
|
1965
|
+
* ```ts
|
|
1966
|
+
* import { HashSet } from "effect"
|
|
1967
|
+
* import * as assert from "node:assert/strict"
|
|
489
1968
|
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
507
|
-
*
|
|
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>(
|
|
2062
|
+
<A, B extends A>(
|
|
2063
|
+
refinement: Refinement<NoInfer<A>, B>
|
|
2064
|
+
): (self: HashSet<A>) => HashSet<B>
|
|
2065
|
+
|
|
510
2066
|
/**
|
|
511
|
-
*
|
|
2067
|
+
* @example
|
|
2068
|
+
*
|
|
2069
|
+
* ```ts
|
|
2070
|
+
* import { HashSet, pipe, type Predicate } from "effect"
|
|
2071
|
+
* import * as assert from "node:assert/strict"
|
|
512
2072
|
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
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
|
-
*
|
|
2087
|
+
* @example
|
|
2088
|
+
*
|
|
2089
|
+
* ```ts
|
|
2090
|
+
* import { HashSet, Predicate } from "effect"
|
|
2091
|
+
* import * as assert from "node:assert/strict"
|
|
519
2092
|
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
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>(
|
|
2109
|
+
<A, B extends A>(
|
|
2110
|
+
self: HashSet<A>,
|
|
2111
|
+
refinement: Refinement<A, B>
|
|
2112
|
+
): HashSet<B>
|
|
2113
|
+
|
|
524
2114
|
/**
|
|
525
|
-
*
|
|
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
|
-
*
|
|
528
|
-
*
|
|
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
|
-
*
|
|
2193
|
+
* @example
|
|
2194
|
+
*
|
|
2195
|
+
* ```ts
|
|
2196
|
+
* import { HashSet, pipe, Predicate } from "effect"
|
|
2197
|
+
* import * as assert from "node:assert/strict"
|
|
546
2198
|
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
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
|
-
*
|
|
552
|
-
*
|
|
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>(
|
|
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
|
-
*
|
|
2229
|
+
* @example
|
|
2230
|
+
*
|
|
2231
|
+
* ```ts
|
|
2232
|
+
* import { HashSet, pipe } from "effect"
|
|
2233
|
+
* import * as assert from "node:assert/strict"
|
|
557
2234
|
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
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
|
-
*
|
|
563
|
-
*
|
|
2240
|
+
* assert.deepStrictEqual(excluded, HashSet.make(1, 3, 5))
|
|
2241
|
+
* assert.deepStrictEqual(satisfying, HashSet.make(0, 2, 4))
|
|
2242
|
+
* ```
|
|
564
2243
|
*/
|
|
565
|
-
<A>(
|
|
2244
|
+
<A>(
|
|
2245
|
+
predicate: Predicate<NoInfer<A>>
|
|
2246
|
+
): (self: HashSet<A>) => [excluded: HashSet<A>, satisfying: HashSet<A>]
|
|
2247
|
+
|
|
566
2248
|
/**
|
|
567
|
-
*
|
|
2249
|
+
* @example
|
|
568
2250
|
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
2251
|
+
* ```ts
|
|
2252
|
+
* import { HashSet, pipe, Predicate } from "effect"
|
|
2253
|
+
* import * as assert from "node:assert/strict"
|
|
572
2254
|
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
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>(
|
|
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
|
-
*
|
|
2284
|
+
* @example
|
|
2285
|
+
*
|
|
2286
|
+
* ```ts
|
|
2287
|
+
* import { HashSet } from "effect"
|
|
2288
|
+
* import * as assert from "node:assert/strict"
|
|
579
2289
|
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
2290
|
+
* const [excluded, satisfying] = HashSet.partition(
|
|
2291
|
+
* HashSet.make(0, 1, 2, 3, 4, 5),
|
|
2292
|
+
* (n) => n % 2 === 0
|
|
2293
|
+
* )
|
|
583
2294
|
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
2295
|
+
* assert.deepStrictEqual(excluded, HashSet.make(1, 3, 5))
|
|
2296
|
+
* assert.deepStrictEqual(satisfying, HashSet.make(0, 2, 4))
|
|
2297
|
+
* ```
|
|
586
2298
|
*/
|
|
587
|
-
<A>(
|
|
2299
|
+
<A>(
|
|
2300
|
+
self: HashSet<A>,
|
|
2301
|
+
predicate: Predicate<A>
|
|
2302
|
+
): [excluded: HashSet<A>, satisfying: HashSet<A>]
|
|
588
2303
|
} = HS.partition
|