Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

TxHashSet

Transactional hash sets for storing unique values inside Effect transactions.

A TxHashSet keeps an immutable HashSet inside a TxRef, so membership checks and updates can commit atomically with other transactional operations. Use it when several pieces of shared transactional state must change together, such as adding a value only after checking related state. The module includes the usual set operations, including adding, removing, membership checks, set algebra, mapping, filtering, reducing, and conversion back to HashSet.

24 exports Since v2.0.0 Source

Combinators

Creates the difference of two TxHashSets (elements in the first set that are not in the second), returning a new TxHashSet.

Signature

declare const difference: {
<V1>(that: TxHashSet<V1>): <V0>(self: TxHashSet<V0>) => Effect<TxHashSet<V0>>;
<V0, V1>(self: TxHashSet<V0>, that: TxHashSet<V1>): Effect<TxHashSet<V0>>;
}

Example Finding values absent from another set

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const set1 = yield* TxHashSet.make("a", "b", "c")
const set2 = yield* TxHashSet.make("b", "d")
const diff = yield* TxHashSet.difference(set1, set2)
Array.from(yield* TxHashSet.toHashSet(diff)).sort() // => ["a", "c"]
yield* TxHashSet.size(diff) // => 2
})
await Effect.runPromise(program)

Creates the intersection of two TxHashSets, returning a new TxHashSet.

Signature

declare const intersection: {
<V1>(that: TxHashSet<V1>): <V0>(self: TxHashSet<V0>) => Effect<TxHashSet<V1 & V0>>;
<V0, V1>(self: TxHashSet<V0>, that: TxHashSet<V1>): Effect<TxHashSet<V0 & V1>>;
}

Example Finding common values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const set1 = yield* TxHashSet.make("a", "b", "c")
const set2 = yield* TxHashSet.make("b", "c", "d")
const common = yield* TxHashSet.intersection(set1, set2)
Array.from(yield* TxHashSet.toHashSet(common)).sort() // => ["b", "c"]
yield* TxHashSet.size(common) // => 2
})
await Effect.runPromise(program)
Since v2.0.0

Creates the union of two TxHashSets, returning a new TxHashSet.

Signature

declare const union: {
<V1>(that: TxHashSet<V1>): <V0>(self: TxHashSet<V0>) => Effect<TxHashSet<V1 | V0>>;
<V0, V1>(self: TxHashSet<V0>, that: TxHashSet<V1>): Effect<TxHashSet<V0 | V1>>;
}

Example Combining sets with union

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const set1 = yield* TxHashSet.make("a", "b")
const set2 = yield* TxHashSet.make("b", "c")
const combined = yield* TxHashSet.union(set1, set2)
Array.from(yield* TxHashSet.toHashSet(combined)).sort() // => ["a", "b", "c"]
yield* TxHashSet.size(combined) // => 3
})
await Effect.runPromise(program)

Constructors

Since v2.0.0

Creates an empty TxHashSet.

Signature

declare function empty<V = never>(): Effect<TxHashSet<V>>

Example Creating an empty transactional hash set

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const txSet = yield* TxHashSet.empty<string>()
yield* TxHashSet.size(txSet) // => 0
yield* TxHashSet.isEmpty(txSet) // => true
// Add some values
yield* TxHashSet.add(txSet, "hello")
yield* TxHashSet.add(txSet, "world")
yield* TxHashSet.size(txSet) // => 2
})
await Effect.runPromise(program)

Creates a TxHashSet from an existing HashSet.

Signature

declare function fromHashSet<V>(hashSet: HashSet<V>): Effect<TxHashSet<V>>

Example Creating a transactional hash set from a HashSet

import { Effect, HashSet, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const hashSet = HashSet.make("x", "y", "z")
const txSet = yield* TxHashSet.fromHashSet(hashSet)
yield* TxHashSet.size(txSet) // => 3
yield* TxHashSet.has(txSet, "y") // => true
// Original hashSet is unchanged when txSet is modified
yield* TxHashSet.add(txSet, "w")
HashSet.size(hashSet) // => 3
yield* TxHashSet.size(txSet) // => 4
})
await Effect.runPromise(program)

Creates a TxHashSet from an iterable collection of values.

Signature

declare function fromIterable<V>(values: Iterable<V>): Effect<TxHashSet<V>>

Example Creating a transactional hash set from an iterable

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const fromArray = yield* TxHashSet.fromIterable(["a", "b", "c", "b", "a"])
yield* TxHashSet.size(fromArray) // => 3
const fromSet = yield* TxHashSet.fromIterable(new Set([1, 2, 3]))
yield* TxHashSet.size(fromSet) // => 3
const fromString = yield* TxHashSet.fromIterable("hello")
Array.from(yield* TxHashSet.toHashSet(fromString)).sort() // => ["e", "h", "l", "o"]
})
await Effect.runPromise(program)
Since v2.0.0

Creates a TxHashSet from a variable number of values.

Signature

declare function make<Values extends readonly Array<any>>(...values: Values): Effect<TxHashSet<Values[number]>>

Example Creating transactional hash sets from values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const fruits = yield* TxHashSet.make("apple", "banana", "cherry")
yield* TxHashSet.size(fruits) // => 3
const numbers = yield* TxHashSet.make(1, 2, 3, 2, 1) // Duplicates ignored
yield* TxHashSet.size(numbers) // => 3
const mixed = yield* TxHashSet.make("hello", 42, true)
yield* TxHashSet.size(mixed) // => 3
})
await Effect.runPromise(program)

Converting

Converts the TxHashSet to an immutable HashSet snapshot.

Signature

declare function toHashSet<V>(self: TxHashSet<V>): Effect<HashSet<V>>

Example Taking a HashSet snapshot

import { Effect, HashSet, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const txSet = yield* TxHashSet.make("x", "y", "z")
const hashSet = yield* TxHashSet.toHashSet(txSet)
HashSet.size(hashSet) // => 3
HashSet.has(hashSet, "y") // => true
// hashSet is a snapshot - modifications to txSet don't affect it
yield* TxHashSet.add(txSet, "w")
HashSet.size(hashSet) // => 3
yield* TxHashSet.size(txSet) // => 4
})
await Effect.runPromise(program)

Filtering

Since v4.0.0

Filters the TxHashSet keeping only values that satisfy the predicate, returning a new TxHashSet.

Signature

declare const filter: {
<V, U>(refinement: Refinement<NoInfer<V>, U>): (self: TxHashSet<V>) => Effect<TxHashSet<U>>;
<V>(predicate: Predicate<NoInfer<V>>): (self: TxHashSet<V>) => Effect<TxHashSet<V>>;
<V, U>(self: TxHashSet<V>, refinement: Refinement<V, U>): Effect<TxHashSet<U>>;
<V>(self: TxHashSet<V>, predicate: Predicate<V>): Effect<TxHashSet<V>>;
}

Example Filtering values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const numbers = yield* TxHashSet.make(1, 2, 3, 4, 5, 6)
const evens = yield* TxHashSet.filter(numbers, (n) => n % 2 === 0)
Array.from(yield* TxHashSet.toHashSet(evens)).sort() // => [2, 4, 6]
yield* TxHashSet.size(evens) // => 3
})
await Effect.runPromise(program)

Folding

Since v2.0.0

Reduces the TxHashSet to a single value by iterating through the values and applying an accumulator function.

Signature

declare const reduce: {
<V, U>(zero: U, f: (accumulator: U, value: V) => U): (self: TxHashSet<V>) => Effect<U>;
<V, U>(self: TxHashSet<V>, zero: U, f: (accumulator: U, value: V) => U): Effect<U>;
}

Example Reducing values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const numbers = yield* TxHashSet.make(1, 2, 3, 4, 5)
yield* TxHashSet.reduce(numbers, 0, (acc, n) => acc + n) // => 15
const strings = yield* TxHashSet.make("a", "b", "c")
String(yield* TxHashSet.reduce(strings, "", (acc, s) => acc + s)).split("").sort().join("") // => "abc"
})
await Effect.runPromise(program)

Getters

Since v2.0.0

Returns the number of values in the TxHashSet.

Signature

declare function size<V>(self: TxHashSet<V>): Effect<number>

Example Getting the set size

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const empty = yield* TxHashSet.empty<string>()
yield* TxHashSet.size(empty) // => 0
const small = yield* TxHashSet.make("a", "b")
yield* TxHashSet.size(small) // => 2
const fromIterable = yield* TxHashSet.fromIterable(["x", "y", "z", "x", "y"])
yield* TxHashSet.size(fromIterable) // => 3
})
await Effect.runPromise(program)

Guards

Checks whether a value is a TxHashSet.

Signature

declare function isTxHashSet(u: unknown): u is TxHashSet<unknown>

Example Checking for a TxHashSet

import { Effect, HashSet, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const txSet = yield* TxHashSet.make(1, 2, 3)
const hashSet = HashSet.make(1, 2, 3)
const array = [1, 2, 3]
TxHashSet.isTxHashSet(txSet) // => true
TxHashSet.isTxHashSet(hashSet) // => false
TxHashSet.isTxHashSet(array) // => false
TxHashSet.isTxHashSet(null) // => false
})
await Effect.runPromise(program)

Mapping

Since v4.0.0

Maps each value in the TxHashSet using the provided function, returning a new TxHashSet.

Signature

declare const map: {
<V, U>(f: (value: V) => U): (self: TxHashSet<V>) => Effect<TxHashSet<U>>;
<V, U>(self: TxHashSet<V>, f: (value: V) => U): Effect<TxHashSet<U>>;
}

Example Mapping values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const numbers = yield* TxHashSet.make(1, 2, 3)
const doubled = yield* TxHashSet.map(numbers, (n) => n * 2)
Array.from(yield* TxHashSet.toHashSet(doubled)).sort() // => [2, 4, 6]
yield* TxHashSet.size(doubled) // => 3
// Mapping can reduce size if function produces duplicates
const strings = yield* TxHashSet.make("apple", "banana", "cherry")
const lengths = yield* TxHashSet.map(strings, (s) => s.length)
Array.from(yield* TxHashSet.toHashSet(lengths)).sort() // => [5, 6]
})
await Effect.runPromise(program)

Models

TxHashSet

interface
Since v4.0.0

A TxHashSet is a transactional hash set data structure that provides atomic operations on unique values within Effect transactions. It uses an immutable HashSet internally with TxRef for transactional semantics, ensuring all operations are performed atomically.

Details

Mutation operations such as add, remove, and clear update the original TxHashSet and return Effect<void> or Effect<boolean>. Transform operations such as union, intersection, difference, map, and filter create new TxHashSet instances and leave the original TxHashSet unchanged.

Signature

interface TxHashSet<in out V> extends Inspectable, Pipeable {
readonly "~effect/TxHashSet": "~effect/TxHashSet";
readonly ref: TxRef<HashSet<V>>;
}

Example Using transactional hash sets

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
// Create a transactional hash set
const txSet = yield* TxHashSet.make("apple", "banana", "cherry")
// Single operations are automatically transactional
yield* TxHashSet.add(txSet, "grape")
yield* TxHashSet.has(txSet, "apple") // => true
// Multi-step atomic operations
yield* Effect.tx(
Effect.gen(function*() {
const hasCherry = yield* TxHashSet.has(txSet, "cherry")
if (hasCherry) {
yield* TxHashSet.remove(txSet, "cherry")
yield* TxHashSet.add(txSet, "orange")
}
})
)
yield* TxHashSet.size(txSet) // => 4
})
await Effect.runPromise(program)

Mutations

Since v2.0.0

Adds a value to the TxHashSet. If the value already exists, the operation has no effect.

Details

This function mutates the original TxHashSet by adding the specified value. It does not return a new TxHashSet reference.

Signature

declare const add: {
<V>(value: V): (self: TxHashSet<V>) => Effect<void>;
<V>(self: TxHashSet<V>, value: V): Effect<void>;
}

Example Adding values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const txSet = yield* TxHashSet.make("a", "b")
yield* TxHashSet.add(txSet, "c")
yield* TxHashSet.size(txSet) // => 3
yield* TxHashSet.has(txSet, "c") // => true
// Adding existing value has no effect
yield* TxHashSet.add(txSet, "a")
yield* TxHashSet.size(txSet) // => 3
})
await Effect.runPromise(program)
Since v4.0.0

Removes all values from the TxHashSet.

Details

This function mutates the original TxHashSet by clearing all values. It does not return a new TxHashSet reference.

Signature

declare function clear<V>(self: TxHashSet<V>): Effect<void>

Example Clearing all values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const txSet = yield* TxHashSet.make("a", "b", "c")
yield* TxHashSet.size(txSet) // => 3
yield* TxHashSet.clear(txSet)
yield* TxHashSet.size(txSet) // => 0
yield* TxHashSet.isEmpty(txSet) // => true
})
await Effect.runPromise(program)
Since v2.0.0

Removes a value from the TxHashSet.

Details

This function mutates the original TxHashSet by removing the specified value. It does not return a new TxHashSet reference.

Signature

declare const remove: {
<V>(value: V): (self: TxHashSet<V>) => Effect<boolean>;
<V>(self: TxHashSet<V>, value: V): Effect<boolean>;
}

Example Removing values

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const txSet = yield* TxHashSet.make("a", "b", "c")
yield* TxHashSet.remove(txSet, "b") // => true
yield* TxHashSet.size(txSet) // => 2
yield* TxHashSet.has(txSet, "b") // => false
// Removing non-existent value returns false
yield* TxHashSet.remove(txSet, "d") // => false
})
await Effect.runPromise(program)

Other

The TxHashSet namespace contains type-level utilities and helper types for working with TxHashSet instances.

Example Extracting value types inside transactions

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
// Create a transactional color set
const colors = yield* TxHashSet.make("red", "green", "blue")
// Extract the value type for reuse
type Color = TxHashSet.TxHashSet.Value<typeof colors> // string
// Use extracted type in functions
const addColor = (color: Color) => TxHashSet.add(colors, color)
yield* addColor("yellow")
yield* TxHashSet.has(colors, "yellow") // => true
})
await Effect.runPromise(program)

Predicates

Since v4.0.0

Checks whether all values in the TxHashSet satisfy the predicate.

Signature

declare const every: {
<V>(predicate: Predicate<V>): (self: TxHashSet<V>) => Effect<boolean>;
<V>(self: TxHashSet<V>, predicate: Predicate<V>): Effect<boolean>;
}

Example Testing whether every value matches

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const numbers = yield* TxHashSet.make(2, 4, 6, 8)
yield* TxHashSet.every(numbers, (n) => n % 2 === 0) // => true
yield* TxHashSet.every(numbers, (n) => n > 5) // => false
const empty = yield* TxHashSet.empty<number>()
yield* TxHashSet.every(empty, (n) => n > 0) // => true
})
await Effect.runPromise(program)
Since v2.0.0

Checks whether the TxHashSet contains the specified value.

Signature

declare const has: {
<V>(value: V): (self: TxHashSet<V>) => Effect<boolean>;
<V>(self: TxHashSet<V>, value: V): Effect<boolean>;
}

Example Checking membership

import { Effect, Equal, Hash, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const txSet = yield* TxHashSet.make("apple", "banana", "cherry")
yield* TxHashSet.has(txSet, "apple") // => true
yield* TxHashSet.has(txSet, "grape") // => false
// Works with any type that implements Equal
class Person implements Equal.Equal {
constructor(readonly name: string) {}
[Equal.symbol](other: unknown) {
return other instanceof Person && this.name === other.name
}
[Hash.symbol](): number {
return Hash.string(this.name)
}
}
const people = yield* TxHashSet.make(new Person("Alice"), new Person("Bob"))
yield* TxHashSet.has(people, new Person("Alice")) // => true
})
await Effect.runPromise(program)
Since v2.0.0

Checks whether the TxHashSet is empty.

Signature

declare function isEmpty<V>(self: TxHashSet<V>): Effect<boolean>

Example Checking whether a set is empty

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const empty = yield* TxHashSet.empty<string>()
yield* TxHashSet.isEmpty(empty) // => true
const nonEmpty = yield* TxHashSet.make("a")
yield* TxHashSet.isEmpty(nonEmpty) // => false
})
await Effect.runPromise(program)

Checks whether the TxHashSet is non-empty.

Signature

declare function isNonEmpty<V>(self: TxHashSet<V>): Effect<boolean>

Example Checking whether a set is non-empty

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const empty = yield* TxHashSet.empty<string>()
const emptyResult = yield* TxHashSet.isNonEmpty(empty)
const nonEmpty = yield* TxHashSet.make("a")
const nonEmptyResult = yield* TxHashSet.isNonEmpty(nonEmpty)
return [emptyResult, nonEmptyResult] as const
})
await Effect.runPromise(program) // => [false, true]
Since v4.0.0

Checks whether a TxHashSet is a subset of another TxHashSet.

Signature

declare const isSubset: {
<V1>(that: TxHashSet<V1>): <V0>(self: TxHashSet<V0>) => Effect<boolean>;
<V0, V1>(self: TxHashSet<V0>, that: TxHashSet<V1>): Effect<boolean>;
}

Example Checking subset relationships

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const small = yield* TxHashSet.make("a", "b")
const large = yield* TxHashSet.make("a", "b", "c", "d")
const other = yield* TxHashSet.make("x", "y")
yield* TxHashSet.isSubset(small, large) // => true
yield* TxHashSet.isSubset(large, small) // => false
yield* TxHashSet.isSubset(small, other) // => false
yield* TxHashSet.isSubset(small, small) // => true
})
await Effect.runPromise(program)
Since v4.0.0

Checks whether at least one value in the TxHashSet satisfies the predicate.

Signature

declare const some: {
<V>(predicate: Predicate<V>): (self: TxHashSet<V>) => Effect<boolean>;
<V>(self: TxHashSet<V>, predicate: Predicate<V>): Effect<boolean>;
}

Example Testing whether some values match

import { Effect, TxHashSet } from "effect"
const program = Effect.gen(function*() {
const numbers = yield* TxHashSet.make(1, 2, 3, 4, 5)
yield* TxHashSet.some(numbers, (n) => n > 3) // => true
yield* TxHashSet.some(numbers, (n) => n > 10) // => false
const empty = yield* TxHashSet.empty<number>()
yield* TxHashSet.some(empty, (n) => n > 0) // => false
})
await Effect.runPromise(program)