or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

concurrency-fibers.mdcontext-services.mddata-structures.mdeffect-core.mderror-observability.mdfunction-utilities.mdindex.mdlayer-system.mdschema-validation.mdstreaming.md
tile.json

concurrency-fibers.mddocs/

Concurrency & Fibers

Lightweight virtual threading system with Fiber for structured concurrency, enabling safe parallel execution, resource management, and cooperative multitasking.

Capabilities

Fiber Operations

interface Fiber<out A, out E = never> extends Pipeable {}

declare namespace Fiber {
  /**
   * Creates a successful fiber
   */
  function succeed<A>(value: A): Fiber<A>;
  
  /**
   * Creates a failed fiber
   */
  function fail<E>(error: E): Fiber<never, E>;
  
  /**
   * Waits for fiber completion
   */
  function await<A, E>(self: Fiber<A, E>): Effect<Exit<A, E>>;
  
  /**
   * Joins a fiber (propagates failure)
   */
  function join<A, E>(self: Fiber<A, E>): Effect<A, E>;
  
  /**
   * Interrupts a fiber
   */
  function interrupt<A, E>(self: Fiber<A, E>): Effect<Exit<A, E>>;
  
  /**
   * Maps over fiber result
   */
  function map<A, B>(f: (a: A) => B): <E>(self: Fiber<A, E>) => Fiber<B, E>;
}

Effect Concurrency

declare namespace Effect {
  /**
   * Forks an effect into a new fiber
   */
  function fork<A, E, R>(self: Effect<A, E, R>): Effect<Fiber<A, E>, never, R>;
  
  /**
   * Forks as daemon fiber
   */
  function forkDaemon<A, E, R>(self: Effect<A, E, R>): Effect<Fiber<A, E>, never, R>;
  
  /**
   * Races two effects
   */
  function race<A, E, R>(self: Effect<A, E, R>): <A2, E2, R2>(that: Effect<A2, E2, R2>) => Effect<A | A2, E | E2, R | R2>;
  
  /**
   * Executes effects in parallel
   */
  function all<Effects extends Iterable<Effect<any, any, any>>>(
    effects: Effects
  ): Effect<
    [Effect.Success<Effects[number]>],
    Effect.Error<Effects[number]>,
    Effect.Context<Effects[number]>
  >;
  
  /**
   * Executes with timeout
   */
  function timeout(duration: Duration): <A, E, R>(self: Effect<A, E, R>) => Effect<Option<A>, E, R>;
}

Usage Examples:

import { Effect, Fiber, Duration, pipe } from "effect";

// Basic forking and joining
const computation = Effect.gen(function* () {
  const fiber1 = yield* Effect.fork(Effect.succeed(1));
  const fiber2 = yield* Effect.fork(Effect.succeed(2));
  
  const result1 = yield* Fiber.join(fiber1);
  const result2 = yield* Fiber.join(fiber2);
  
  return result1 + result2;
});

// Racing operations
const quickTimeout = pipe(
  slowOperation,
  Effect.race(Effect.sleep(Duration.seconds(5)))
);

// Parallel execution
const parallelWork = Effect.all([
  fetchUser("1"),
  fetchUser("2"), 
  fetchUser("3")
]);

Software Transactional Memory (STM)

STM provides composable, thread-safe concurrent programming through transactional memory.

interface STM<out A, out E = never, out R = never> extends Pipeable {}

declare namespace STM {
  /**
   * Creates a successful STM
   */
  function succeed<A>(value: A): STM<A>;
  
  /**
   * Creates a failed STM
   */
  function fail<E>(error: E): STM<never, E>;
  
  /**
   * Suspends an STM computation
   */
  function suspend<A, E, R>(stm: LazyArg<STM<A, E, R>>): STM<A, E, R>;
  
  /**
   * Maps over STM value
   */
  function map<A, B>(f: (a: A) => B): <E, R>(self: STM<A, E, R>) => STM<B, E, R>;
  
  /**
   * FlatMaps over STM value
   */
  function flatMap<A, B, E2, R2>(
    f: (a: A) => STM<B, E2, R2>
  ): <E1, R1>(self: STM<A, E1, R1>) => STM<B, E1 | E2, R1 | R2>;
  
  /**
   * Commits STM transaction
   */
  function commit<A, E, R>(self: STM<A, E, R>): Effect<A, E, R>;
  
  /**
   * Retries STM until successful
   */
  function retry(): STM<never>;
  
  /**
   * Combines STM transactions with orElse semantics
   */
  function orElse<A2, E2, R2>(
    that: LazyArg<STM<A2, E2, R2>>
  ): <A1, E1, R1>(self: STM<A1, E1, R1>) => STM<A1 | A2, E1 | E2, R1 | R2>;
}

Micro Effects

Lightweight Effect system optimized for performance with reduced feature set.

interface Micro<out A, out E = never, out R = never> extends Pipeable {}

declare namespace Micro {
  /**
   * Creates a successful Micro
   */
  function succeed<A>(value: A): Micro<A>;
  
  /**
   * Creates a failed Micro
   */
  function fail<E>(error: E): Micro<never, E>;
  
  /**
   * Creates Micro from sync computation
   */
  function sync<A>(thunk: LazyArg<A>): Micro<A>;
  
  /**
   * Maps over Micro value
   */
  function map<A, B>(f: (a: A) => B): <E, R>(self: Micro<A, E, R>) => Micro<B, E, R>;
  
  /**
   * FlatMaps over Micro value
   */
  function flatMap<A, B, E2, R2>(
    f: (a: A) => Micro<B, E2, R2>
  ): <E1, R1>(self: Micro<A, E1, R1>) => Micro<B, E1 | E2, R1 | R2>;
  
  /**
   * Runs Micro to Promise
   */
  function runPromise<A, E>(micro: Micro<A, E>): Promise<A>;
  
  /**
   * Runs Micro synchronously
   */
  function runSync<A, E>(micro: Micro<A, E>): A;
  
  /**
   * Forks Micro into fiber
   */
  function fork<A, E, R>(self: Micro<A, E, R>): Micro<MicroFiber<A, E>, never, R>;
}

interface MicroFiber<out A, out E = never> extends Pipeable {
  /**
   * Awaits fiber completion
   */
  await(): Micro<MicroExit<A, E>>;
  
  /**
   * Joins fiber result
   */
  join(): Micro<A, E>;
  
  /**
   * Interrupts the fiber
   */
  interrupt(): Micro<MicroExit<A, E>>;
}

Types

interface Duration {
  readonly _tag: "Duration";
  readonly millis: number;
}

interface FiberId {
  readonly _tag: "FiberId";
  readonly id: number;
  readonly startTimeMillis: number;
}