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