or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

algebraic.mdarray.mdeither.mdfunction.mdindex.mdio.mdoption.mdpipeable.mdrecord.mdtask-either.mdtask.mdtype-classes.md
tile.json

task.mddocs/

Task Operations

Task represents asynchronous computations that never fail. Tasks are lazy and only executed when the run() method is called, returning a Promise. For computations that may fail, use TaskEither.

Capabilities

Core Construction

Create Task instances from values and async functions.

/**
 * Create Task from pure value
 * @param a - Value to wrap in Task
 * @returns Task that resolves to the value
 */
function of<A>(a: A): Task<A>;

/**
 * Create Task from Promise-returning function
 * @param f - Function returning Promise
 * @returns Task that executes function when run
 */
function task<A>(f: Lazy<Promise<A>>): Task<A>;

/**
 * Create Task from existing Promise
 * @param promise - Promise to wrap
 * @returns Task that resolves with the Promise
 */
function fromPromise<A>(promise: Promise<A>): Task<A>;

/**
 * Never-resolving Task (infinite computation)
 */
const never: Task<never>;

/**
 * Create Task that delays execution
 * @param millis - Milliseconds to delay
 * @returns Task that completes after delay
 */
function delay(millis: number): Task<void>;

Usage Examples:

import { Task, of as taskOf, delay } from "fp-ts/lib/Task";

// Pure value
const constantTask = taskOf(42);
constantTask.run().then(result => console.log(result)); // 42

// Async computation
const fetchTask = new Task(() => 
  fetch("/api/data").then(res => res.json())
);

// Delayed execution
const delayedTask = delay(1000);
delayedTask.run().then(() => console.log("1 second later"));

Transformation Operations

Transform Task computations while preserving the async context.

/**
 * Map function over Task result
 * @param f - Transformation function
 * @returns Function that maps over Task
 */
function map<A, B>(f: (a: A) => B): (fa: Task<A>) => Task<B>;

/**
 * Apply function in Task to value in Task
 * @param fab - Task containing function
 * @returns Function that applies function to Task value
 */
function ap<A, B>(fab: Task<(a: A) => B>): (fa: Task<A>) => Task<B>;

/**
 * Sequence two Tasks, keeping first result
 * @param fb - Second Task to execute
 * @returns Function that sequences Tasks
 */
function applyFirst<A, B>(fb: Task<B>): (fa: Task<A>) => Task<A>;

/**
 * Sequence two Tasks, keeping second result
 * @param fb - Second Task to execute
 * @returns Function that sequences Tasks
 */
function applySecond<A, B>(fb: Task<B>): (fa: Task<A>) => Task<B>;

Usage Examples:

import { Task, map, ap } from "fp-ts/lib/Task";

// Transform result
const numberTask = new Task(() => Promise.resolve(21));
const doubledTask = map((n: number) => n * 2)(numberTask);
doubledTask.run().then(result => console.log(result)); // 42

// Apply function
const addTask = new Task(() => Promise.resolve((x: number) => (y: number) => x + y));
const xTask = new Task(() => Promise.resolve(10));
const yTask = new Task(() => Promise.resolve(20));
const sumTask = ap(ap(addTask)(xTask))(yTask);
sumTask.run().then(sum => console.log(sum)); // 30

Sequencing Operations

Chain Task computations in sequence.

/**
 * Chain Task computations
 * @param f - Function returning Task
 * @returns Function that chains Tasks
 */
function chain<A, B>(f: (a: A) => Task<B>): (fa: Task<A>) => Task<B>;

/**
 * Flatten nested Task
 * @param mma - Task containing Task
 * @returns Flattened Task
 */
function flatten<A>(mma: Task<Task<A>>): Task<A>;

Usage Examples:

import { Task, chain } from "fp-ts/lib/Task";

// Chain async operations
const getUserId = new Task(() => Promise.resolve("user123"));
const fetchUser = (id: string) => new Task(() => 
  fetch(`/api/users/${id}`).then(res => res.json())
);

const userTask = chain(fetchUser)(getUserId);
userTask.run().then(user => console.log(user));

Parallel Execution

Execute multiple Tasks in parallel.

/**
 * Execute Tasks in parallel, collecting results
 * @param tasks - Array of Tasks to execute
 * @returns Task that resolves to array of results
 */
function sequenceArray<A>(tasks: Array<Task<A>>): Task<Array<A>>;

/**
 * Execute Tasks in parallel, transforming with function
 * @param f - Function to apply to each element
 * @returns Function that maps over array with parallel execution
 */
function traverseArray<A, B>(f: (a: A) => Task<B>): (as: Array<A>) => Task<Array<B>>;

/**
 * Race multiple Tasks, returning first to complete
 * @param tasks - Array of Tasks to race
 * @returns Task that resolves with first result
 */
function race<A>(tasks: Array<Task<A>>): Task<A>;

Usage Examples:

import { Task, sequenceArray, traverseArray } from "fp-ts/lib/Task";

// Parallel execution
const task1 = new Task(() => Promise.resolve(1));
const task2 = new Task(() => Promise.resolve(2));
const task3 = new Task(() => Promise.resolve(3));

const allTasks = sequenceArray([task1, task2, task3]);
allTasks.run().then(results => console.log(results)); // [1, 2, 3]

// Transform array in parallel
const urls = ["/api/data1", "/api/data2", "/api/data3"];
const fetchUrl = (url: string) => new Task(() => fetch(url).then(res => res.json()));
const allData = traverseArray(fetchUrl)(urls);
allData.run().then(data => console.log(data));

Type Class Instances

Task implements various type class instances for generic operations.

/**
 * Main Task type class instances
 */
const task: Monad1<URI> & MonadIO1<URI> & MonadTask1<URI>;

/**
 * Semigroup instance for Task
 * @param S - Semigroup for contained type
 * @returns Semigroup that combines Task results
 */
function getSemigroup<A>(S: Semigroup<A>): Semigroup<Task<A>>;

/**
 * Monoid instance for Task
 * @param M - Monoid for contained type
 * @returns Monoid that combines Task results
 */
function getMonoid<A>(M: Monoid<A>): Monoid<Task<A>>;

/**
 * Race-based Monoid (first Task to complete wins)
 * @returns Monoid where concat races Tasks
 */
function getRaceMonoid<A>(): Monoid<Task<A>>;

Timing and Delays

Control timing of Task execution.

/**
 * Add delay before Task execution
 * @param millis - Milliseconds to delay
 * @returns Function that delays Task
 */
function delay<A>(millis: number): (fa: Task<A>) => Task<A>;

/**
 * Timeout Task execution
 * @param millis - Timeout in milliseconds
 * @param onTimeout - Value to return on timeout
 * @returns Function that adds timeout to Task
 */
function timeout<A>(millis: number, onTimeout: A): (fa: Task<A>) => Task<A>;

/**
 * Measure Task execution time
 * @param fa - Task to measure
 * @returns Task returning tuple of [result, milliseconds]
 */
function time<A>(fa: Task<A>): Task<[A, number]>;

Retry and Error Recovery

Although Task never fails, these utilities help with robust execution.

/**
 * Retry Task execution with exponential backoff
 * @param maxRetries - Maximum number of retries
 * @param delay - Initial delay in milliseconds
 * @returns Function that adds retry logic to Task
 */
function retry<A>(maxRetries: number, delay: number): (fa: Task<A>) => Task<A>;

/**
 * Execute Task with fallback on failure
 * @param fallback - Task to execute if original fails
 * @returns Function that adds fallback to Task
 */
function alt<A>(fallback: Task<A>): (fa: Task<A>) => Task<A>;

Interoperability

Convert between Task and other effect types.

/**
 * Convert IO to Task
 * @param ma - IO to convert
 * @returns Task that executes IO
 */
function fromIO<A>(ma: IO<A>): Task<A>;

/**
 * Convert Task to TaskEither with error handling
 * @param f - Task that may reject
 * @param onRejected - Function to handle rejection
 * @returns TaskEither with proper error handling
 */
function tryCatch<L, A>(f: Lazy<Promise<A>>, onRejected: (reason: unknown) => L): TaskEither<L, A>;

Usage Examples:

import { Task, fromIO, tryCatch } from "fp-ts/lib/Task";
import { IO } from "fp-ts/lib/IO";

// Convert IO to Task
const syncIO = new IO(() => "sync result");
const asyncTask = fromIO(syncIO);
asyncTask.run().then(result => console.log(result)); // "sync result"

// Safe async operation
const safeTask = tryCatch(
  () => fetch("/api/data").then(res => res.json()),
  (error) => `Fetch failed: ${error}`
);

Types

// Core Task type
class Task<A> {
  readonly _A!: A;
  readonly _URI!: URI;
  
  constructor(readonly run: Lazy<Promise<A>>) {}
  
  // Instance methods (deprecated in favor of pipeable operations)
  map<B>(f: (a: A) => B): Task<B>;
  ap<B>(fab: Task<(a: A) => B>): Task<B>;
  chain<B>(f: (a: A) => Task<B>): Task<B>;
  
  // Utility methods
  inspect(): string;
  toString(): string;
}

// URI for type-level programming
const URI = 'Task';
type URI = typeof URI;

// Lazy Promise type
type Lazy<A> = () => A;