(self: TxReentrantLock): Effect.Effect<number>Releases one write lock held by the current fiber.
When to use
Use to leave a manually acquired write lock.
Details
Returns the remaining number of write locks held by this fiber.
Example (Releasing a write lock)
import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
yield* TxReentrantLock.acquireWrite(lock)
const remaining = yield* TxReentrantLock.releaseWrite(lock)
console.log(remaining) // 0
})export const const releaseWrite: (
self: TxReentrantLock
) => Effect.Effect<number>
Releases one write lock held by the current fiber.
When to use
Use to leave a manually acquired write lock.
Details
Returns the remaining number of write locks held by this fiber.
Example (Releasing a write lock)
import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
yield* TxReentrantLock.acquireWrite(lock)
const remaining = yield* TxReentrantLock.releaseWrite(lock)
console.log(remaining) // 0
})
releaseWrite = (self: TxReentrantLock(parameter) self: {
stateRef: TxRef.TxRef<LockState>;
toString: () => string;
toJSON: () => unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: TxReentrantLock): import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<number> =>
import EffectEffect.const withFiber: <
A,
E = never,
R = never
>(
evaluate: (
fiber: Fiber<unknown, unknown>
) => Effect<A, E, R>
) => Effect<A, E, R>
Provides access to the current fiber within an effect computation.
Example (Reading the current fiber)
import { Effect } from "effect"
const program = Effect.withFiber((fiber) =>
Effect.succeed(`Fiber ID: ${fiber.id}`)
)
Effect.runPromise(program).then(console.log)
// Output: Fiber ID: 1
withFiber((fiber: Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber) =>
import EffectEffect.const gen: {
<Eff extends Effect<any, any, any>, AEff>(
f: () => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
<Self, Eff extends Effect<any, any, any>, AEff>(
options: { readonly self: Self },
f: (this: Self) => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
}
gen(function*() {
const const state: LockStateconst state: {
readers: HashMap.HashMap<number, number>;
writer: Option.Option<readonly [fiberId: number, count: number]>;
}
state = yield* import TxRefTxRef.const get: <A>(
self: TxRef<A>
) => Effect.Effect<A>
Reads the current value of the TxRef.
When to use
Use to read the current value of a TxRef.
Example (Reading transactional references)
import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
const counter = yield* TxRef.make(42)
// Read the value within a transaction
const value = yield* Effect.tx(
TxRef.get(counter)
)
console.log(value) // 42
})
get(self: TxReentrantLock(parameter) self: {
stateRef: TxRef.TxRef<LockState>;
toString: () => string;
toJSON: () => unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self.TxReentrantLock.stateRef: TxRef.TxRef<LockState>(property) TxReentrantLock.stateRef: {
version: number;
pending: Map<unknown, () => void>;
value: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
stateRef)
const const fiberId: numberfiberId = fiber: Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber.Fiber<out A, out E = never>.id: numberid
if (import OptionOption.const isNone: <A>(
self: Option<A>
) => self is None<A>
Checks whether an Option is None (absent).
When to use
Use when you need to branch on an absent Option before accessing .value.
Details
- Acts as a type guard, narrowing to
None<A>
Example (Checking for None)
import { Option } from "effect"
console.log(Option.isNone(Option.some(1)))
// Output: false
console.log(Option.isNone(Option.none()))
// Output: true
isNone(const state: LockStateconst state: {
readers: HashMap.HashMap<number, number>;
writer: Option.Option<readonly [fiberId: number, count: number]>;
}
state.LockState.writer: Option.Option<readonly [fiberId: number, count: number]>writer) || const state: LockStateconst state: {
readers: HashMap.HashMap<number, number>;
writer: Option.Option<readonly [fiberId: number, count: number]>;
}
state.LockState.writer: Option.Option<readonly [fiberId: number, count: number]>(property) LockState.writer: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
writer.Some<readonly [fiberId: number, count: number]>.value: readonly [fiberId: number, count: number](property) Some<readonly [fiberId: number, count: number]>.value: {
0: number;
1: number;
length: 2;
toString: () => string;
toLocaleString: { (): string; (locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string };
concat: { (...items: Array<ConcatArray<number>>): Array<number>; (...items: Array<number | ConcatArray<number>>): Array<number> };
join: (separator?: string) => string;
slice: (start?: number, end?: number) => Array<number>;
indexOf: (searchElement: number, fromIndex?: number) => number;
lastIndexOf: (searchElement: number, fromIndex?: number) => number;
every: { (predicate: (value: number, index: number, array: ReadonlyArray<number>) => value is S, thisArg?: any): this is readonly S[]; (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any): boolean };
some: (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any) => boolean;
forEach: (callbackfn: (value: number, index: number, array: ReadonlyArray<number>) => void, thisArg?: any) => void;
map: (callbackfn: (value: number, index: number, array: ReadonlyArray<number>) => U, thisArg?: any) => Array<U>;
filter: { (predicate: (value: number, index: number, array: ReadonlyArray<number>) => value is S, thisArg?: any): Array<S>; (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any): Array<number> };
reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<number>) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<numb…;
reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<number>) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<numb…;
find: { (predicate: (value: number, index: number, obj: ReadonlyArray<number>) => value is S, thisArg?: any): S | undefined; (predicate: (value: number, index: number, obj: ReadonlyArray<number>) => unknown, thisArg?: any): number | undefined };
findIndex: (predicate: (value: number, index: number, obj: ReadonlyArray<number>) => unknown, thisArg?: any) => number;
entries: () => ArrayIterator<[number, number]>;
keys: () => ArrayIterator<number>;
values: () => ArrayIterator<number>;
includes: (searchElement: number, fromIndex?: number) => boolean;
flatMap: (callback: (this: This, value: number, index: number, array: Array<number>) => U | ReadonlyArray<U>, thisArg?: This | undefined) => Array<U>;
flat: (this: A, depth?: D | undefined) => Array<FlatArray<A, D>>;
at: (index: number) => number | undefined;
findLast: { (predicate: (value: number, index: number, array: ReadonlyArray<number>) => value is S, thisArg?: any): S | undefined; (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any): number | undefine…;
findLastIndex: (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any) => number;
toReversed: () => Array<number>;
toSorted: (compareFn?: ((a: number, b: number) => number) | undefined) => Array<number>;
toSpliced: { (start: number, deleteCount: number, ...items: Array<number>): Array<number>; (start: number, deleteCount?: number): Array<number> };
with: (index: number, value: number) => Array<number>;
}
value[0] !== const fiberId: numberfiberId) return 0
const const newCount: numbernewCount = const state: LockStateconst state: {
readers: HashMap.HashMap<number, number>;
writer: Option.Option<readonly [fiberId: number, count: number]>;
}
state.LockState.writer: Option.Option<readonly [fiberId: number, count: number]>(property) LockState.writer: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
writer.Some<readonly [fiberId: number, count: number]>.value: readonly [fiberId: number, count: number](property) Some<readonly [fiberId: number, count: number]>.value: {
0: number;
1: number;
length: 2;
toString: () => string;
toLocaleString: { (): string; (locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string };
concat: { (...items: Array<ConcatArray<number>>): Array<number>; (...items: Array<number | ConcatArray<number>>): Array<number> };
join: (separator?: string) => string;
slice: (start?: number, end?: number) => Array<number>;
indexOf: (searchElement: number, fromIndex?: number) => number;
lastIndexOf: (searchElement: number, fromIndex?: number) => number;
every: { (predicate: (value: number, index: number, array: ReadonlyArray<number>) => value is S, thisArg?: any): this is readonly S[]; (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any): boolean };
some: (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any) => boolean;
forEach: (callbackfn: (value: number, index: number, array: ReadonlyArray<number>) => void, thisArg?: any) => void;
map: (callbackfn: (value: number, index: number, array: ReadonlyArray<number>) => U, thisArg?: any) => Array<U>;
filter: { (predicate: (value: number, index: number, array: ReadonlyArray<number>) => value is S, thisArg?: any): Array<S>; (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any): Array<number> };
reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<number>) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<numb…;
reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<number>) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: ReadonlyArray<numb…;
find: { (predicate: (value: number, index: number, obj: ReadonlyArray<number>) => value is S, thisArg?: any): S | undefined; (predicate: (value: number, index: number, obj: ReadonlyArray<number>) => unknown, thisArg?: any): number | undefined };
findIndex: (predicate: (value: number, index: number, obj: ReadonlyArray<number>) => unknown, thisArg?: any) => number;
entries: () => ArrayIterator<[number, number]>;
keys: () => ArrayIterator<number>;
values: () => ArrayIterator<number>;
includes: (searchElement: number, fromIndex?: number) => boolean;
flatMap: (callback: (this: This, value: number, index: number, array: Array<number>) => U | ReadonlyArray<U>, thisArg?: This | undefined) => Array<U>;
flat: (this: A, depth?: D | undefined) => Array<FlatArray<A, D>>;
at: (index: number) => number | undefined;
findLast: { (predicate: (value: number, index: number, array: ReadonlyArray<number>) => value is S, thisArg?: any): S | undefined; (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any): number | undefine…;
findLastIndex: (predicate: (value: number, index: number, array: ReadonlyArray<number>) => unknown, thisArg?: any) => number;
toReversed: () => Array<number>;
toSorted: (compareFn?: ((a: number, b: number) => number) | undefined) => Array<number>;
toSpliced: { (start: number, deleteCount: number, ...items: Array<number>): Array<number>; (start: number, deleteCount?: number): Array<number> };
with: (index: number, value: number) => Array<number>;
}
value[1] - 1
const const newWriter: Option.Option<
readonly [number, number]
>
newWriter = const newCount: numbernewCount <= 0
? import OptionOption.const none: <A = never>() => Option<A>Creates an Option representing the absence of a value.
When to use
Use to represent a missing or uninitialized value, such as returning "no
result" from a function.
Details
- Returns
Option<never>, which is a subtype of Option<A> for any A
- Always returns the same singleton instance
Example (Creating an empty Option)
import { Option } from "effect"
// ┌─── Option<never>
// ▼
const noValue = Option.none()
console.log(noValue)
// Output: { _id: 'Option', _tag: 'None' }
none<readonly [number, number]>()
: import OptionOption.const some: <A>(value: A) => Option<A>Wraps the given value into an Option to represent its presence.
When to use
Use to wrap a known present value as Option
- Returning a successful result from a partial function
Details
- Always returns
Some<A>
- Does not filter
null or undefined; use
fromNullishOr
for that
Example (Wrapping a value)
import { Option } from "effect"
// ┌─── Option<number>
// ▼
const value = Option.some(1)
console.log(value)
// Output: { _id: 'Option', _tag: 'Some', value: 1 }
some([const fiberId: numberfiberId, const newCount: numbernewCount] as type const = readonly [number, number]const)
yield* import TxRefTxRef.const set: {
<A>(value: A): (
self: TxRef<A>
) => Effect.Effect<void>
<A>(
self: TxRef<A>,
value: A
): Effect.Effect<void>
}
set(self: TxReentrantLock(parameter) self: {
stateRef: TxRef.TxRef<LockState>;
toString: () => string;
toJSON: () => unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self.TxReentrantLock.stateRef: TxRef.TxRef<LockState>(property) TxReentrantLock.stateRef: {
version: number;
pending: Map<unknown, () => void>;
value: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
stateRef, { ...const state: LockStateconst state: {
readers: HashMap.HashMap<number, number>;
writer: Option.Option<readonly [fiberId: number, count: number]>;
}
state, LockState.writer: Option.Option<readonly [number, number]>writer: const newWriter: Option.Option<
readonly [number, number]
>
newWriter })
return const newCount: numbernewCount
}).Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>>(this: Effect.Effect<number, never, never>, ab: (_: Effect.Effect<number, never, never>) => Effect.Effect<number, never, never>): Effect.Effect<number, never, never> (+21 overloads)pipe(import EffectEffect.const tx: <A, E, R>(
effect: Effect<A, E, R>
) => Effect<A, E, Exclude<R, Transaction>>
Defines a transaction boundary. Transactions are "all or nothing" with respect to changes
made to transactional values (i.e. TxRef) that occur within the transaction body.
Details
If called inside an active transaction, tx composes with the current transaction and reuses
its journal and retry state instead of creating a nested boundary.
Effect transactions are optimistic with retry. A transaction is retried when
its body explicitly calls Effect.txRetry and any accessed transactional
value changes, or when any accessed transactional value changes because a
different transaction commits before the current one.
The outermost tx call creates the transaction boundary and commits or rolls back the full
composed transaction.
Example (Running a transaction)
import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
const ref1 = yield* TxRef.make(0)
const ref2 = yield* TxRef.make(0)
// Nested tx calls compose into the same transaction
yield* Effect.tx(Effect.gen(function*() {
yield* TxRef.set(ref1, 10)
yield* Effect.tx(TxRef.set(ref2, 20))
const sum = (yield* TxRef.get(ref1)) + (yield* TxRef.get(ref2))
console.log(`Transaction sum: ${sum}`)
}))
console.log(`Final ref1: ${yield* TxRef.get(ref1)}`) // 10
console.log(`Final ref2: ${yield* TxRef.get(ref2)}`) // 20
})
tx)
)