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-either.mddocs/

TaskEither Operations

TaskEither represents asynchronous computations that may fail. It combines Task and Either, modeling computations that are both asynchronous and may result in errors. TaskEither is right-biased like Either.

Capabilities

Core Construction

Create TaskEither instances for success and failure cases.

/**
 * Create TaskEither with left (error) value
 * @param l - Error value
 * @returns TaskEither that resolves to Left
 */
function left<L, A>(l: L): TaskEither<L, A>;

/**
 * Create TaskEither with right (success) value  
 * @param a - Success value
 * @returns TaskEither that resolves to Right
 */
function right<L, A>(a: A): TaskEither<L, A>;

/**
 * Create TaskEither from pure value (alias for right)
 * @param a - Success value
 * @returns TaskEither that resolves to Right
 */
function of<L, A>(a: A): TaskEither<L, A>;

/**
 * Create TaskEither from Either
 * @param e - Either to lift into Task context
 * @returns TaskEither with same left/right value
 */
function fromEither<L, A>(e: Either<L, A>): TaskEither<L, A>;

/**
 * Create TaskEither from Task (assumes success)
 * @param fa - Task to lift  
 * @returns TaskEither that cannot fail
 */
function rightTask<L, A>(fa: Task<A>): TaskEither<L, A>;

/**
 * Create failing TaskEither from Task
 * @param fl - Task containing error value
 * @returns TaskEither that always fails
 */
function leftTask<L, A>(fl: Task<L>): TaskEither<L, A>;

Usage Examples:

import { left, right, fromEither, rightTask } from "fp-ts/lib/TaskEither";
import { right as eitherRight, left as eitherLeft } from "fp-ts/lib/Either";
import { Task } from "fp-ts/lib/Task";

// Direct construction
const success = right<string, number>(42);
const failure = left<string, number>("Error occurred");

// From Either
const fromEith = fromEither(eitherRight(100));
fromEith.run().then(result => console.log(result)); // Right(100)

// From Task
const asyncTask = new Task(() => Promise.resolve("data"));
const taskEither = rightTask(asyncTask);
taskEither.run().then(result => console.log(result)); // Right("data")

Safe Execution

Execute functions safely with error handling.

/**
 * Safely execute async function that may reject
 * @param f - Function returning Promise
 * @param onRejected - Function to convert rejection to left value
 * @returns TaskEither with result or error
 */
function tryCatch<L, A>(f: Lazy<Promise<A>>, onRejected: (reason: unknown) => L): TaskEither<L, A>;

/**
 * Safely execute function that may throw
 * @param f - Function that may throw
 * @param onThrown - Function to convert thrown value to left value
 * @returns TaskEither with result or error
 */
function tryCatchK<L, A>(f: Lazy<A>, onThrown: (e: unknown) => L): TaskEither<L, A>;

/**
 * Convert task-returning function to safe TaskEither function
 * @param f - Function returning Task
 * @param onRejected - Function to convert rejection to left value
 * @returns Safe function returning TaskEither
 */
function taskify<L, A, R>(f: (a: A) => Task<R>, onRejected: (reason: unknown) => L): (a: A) => TaskEither<L, R>;

Usage Examples:

import { tryCatch, tryCatchK } from "fp-ts/lib/TaskEither";

// Safe fetch
const safeFetch = (url: string) => tryCatch(
  () => fetch(url).then(res => res.json()),
  (error) => `Fetch failed: ${error}`
);

safeFetch("/api/data").run().then(result => {
  if (result._tag === "Right") {
    console.log("Data:", result.right);
  } else {
    console.log("Error:", result.left);
  }
});

// Safe JSON parse  
const safeParseJSON = (str: string) => tryCatchK(
  () => JSON.parse(str),
  (error) => `Parse error: ${error}`
);

Transformation Operations

Transform TaskEither computations while preserving the async Either context.

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

/**
 * Map function over left value
 * @param f - Transformation function for error
 * @returns Function that maps over left value
 */
function mapLeft<L, M>(f: (l: L) => M): <A>(fa: TaskEither<L, A>) => TaskEither<M, A>;

/**
 * Map over both left and right values
 * @param f - Function for left value
 * @param g - Function for right value
 * @returns Function that maps over both sides
 */
function bimap<L, M, A, B>(f: (l: L) => M, g: (a: A) => B): (fa: TaskEither<L, A>) => TaskEither<M, B>;

Sequencing Operations

Chain TaskEither computations in sequence.

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

/**
 * Chain with access to left value on error
 * @param f - Function to handle left value
 * @returns Function that handles errors
 */
function orElse<L, M, A>(f: (l: L) => TaskEither<M, A>): (fa: TaskEither<L, A>) => TaskEither<M, A>;

Usage Examples:

import { chain, map, tryCatch } from "fp-ts/lib/TaskEither";

// Chain operations
const fetchUser = (id: string) => tryCatch(
  () => fetch(`/api/users/${id}`).then(res => res.json()),
  (error) => `Failed to fetch user: ${error}`
);

const fetchUserPosts = (user: any) => tryCatch(
  () => fetch(`/api/users/${user.id}/posts`).then(res => res.json()),
  (error) => `Failed to fetch posts: ${error}`
);

const userWithPosts = chain(fetchUserPosts)(fetchUser("123"));
userWithPosts.run().then(result => console.log(result));

Pattern Matching and Extraction

Pattern match on TaskEither results and extract values.

/**
 * Pattern match on TaskEither with handlers for both cases
 * @param onLeft - Function to call if result is Left
 * @param onRight - Function to call if result is Right
 * @returns Function that takes TaskEither and returns Task of result
 */
function fold<L, A, R>(onLeft: (l: L) => R, onRight: (a: A) => R): (fa: TaskEither<L, A>) => Task<R>;

/**
 * Extract right value with error handler
 * @param f - Function to convert left value to right type
 * @returns Function that extracts right value or converts left
 */
function getOrElse<L, A>(f: (l: L) => Task<A>): (fa: TaskEither<L, A>) => Task<A>;

/**
 * Extract right value with default Task
 * @param onLeft - Default Task for left case
 * @returns Function that extracts right or returns default
 */
function getOrElseW<L, B>(onLeft: (l: L) => Task<B>): <A>(fa: TaskEither<L, A>) => Task<A | B>;

Usage Examples:

import { fold, getOrElse, right, left } from "fp-ts/lib/TaskEither";
import { Task } from "fp-ts/lib/Task";

const success = right<string, number>(42);
const failure = left<string, number>("Error");

// Pattern matching
const handleResult = fold(
  (error: string) => `Failed: ${error}`,
  (value: number) => `Success: ${value}`
);

handleResult(success).run().then(result => console.log(result)); // "Success: 42"

// Extract with default
const getValueOrZero = getOrElse((_error: string) => Task.of(0));
getValueOrZero(failure).run().then(result => console.log(result)); // 0

Parallel Execution

Execute multiple TaskEithers in parallel.

/**
 * Execute TaskEithers in parallel, collecting results
 * @param tasks - Array of TaskEithers to execute
 * @returns TaskEither that resolves to array of results (fails if any fail)
 */
function sequenceArray<L, A>(tasks: Array<TaskEither<L, A>>): TaskEither<L, Array<A>>;

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

Type Class Instances

TaskEither implements various type class instances.

/**
 * Main TaskEither type class instances
 */
const taskEither: Monad2<URI> & 
                  Bifunctor2<URI> & 
                  Alt2<URI> & 
                  MonadIO2<URI> & 
                  MonadTask2<URI> & 
                  MonadThrow2<URI>;

/**
 * ApplicativeSeq instance (sequential execution)
 */
const taskEitherSeq: Monad2<URI>;

/**
 * Semigroup instance for TaskEither
 * @param S - Semigroup for right type
 * @returns Semigroup that combines right values
 */
function getSemigroup<L, A>(S: Semigroup<A>): Semigroup<TaskEither<L, A>>;

/**
 * Apply semigroup (parallel execution)
 * @param S - Semigroup for right type
 * @returns Semigroup for parallel combination
 */
function getApplySemigroup<L, A>(S: Semigroup<A>): Semigroup<TaskEither<L, A>>;

/**
 * Apply monoid (parallel execution)
 * @param M - Monoid for right type
 * @returns Monoid for parallel combination
 */
function getApplyMonoid<L, A>(M: Monoid<A>): Monoid<TaskEither<L, A>>;

Validation

Accumulating validation errors.

/**
 * Get validation applicative that accumulates left values
 * @param S - Semigroup for left type (error accumulation)
 * @returns Applicative that accumulates errors
 */
function getTaskValidation<L>(S: Semigroup<L>): Monad2C<URI, L> & Alt2C<URI, L>;

Utility Operations

Additional utilities for working with TaskEither.

/**
 * Swap left and right values
 * @param fa - TaskEither to swap
 * @returns TaskEither with swapped left/right
 */
function swap<L, A>(fa: TaskEither<L, A>): TaskEither<A, L>;

/**
 * Filter right value with predicate
 * @param predicate - Predicate to test right value
 * @param onFalse - Value to use if predicate fails
 * @returns Function that filters TaskEither
 */
function filterOrElse<L, A>(predicate: Predicate<A>, onFalse: (a: A) => L): (fa: TaskEither<L, A>) => TaskEither<L, A>;

/**
 * Apply predicate to right value, converting to left on false
 * @param predicate - Predicate to test
 * @param onFalse - Function to convert value to left
 * @returns Function that converts based on predicate
 */
function fromPredicate<L, A>(predicate: Predicate<A>, onFalse: (a: A) => L): (a: A) => TaskEither<L, A>;

Types

// Core TaskEither type
type TaskEither<L, A> = Task<Either<L, A>>;

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

// Related types
type Task<A> = import('./Task').Task<A>;
type Either<L, A> = import('./Either').Either<L, A>;