Standard Toolkit
Packages@accelint/coreCombinators

composition

Composes two functions, passing the result of one to the other

Composes two functions, applying the second function first and passing its result to the first function. Also known as the B combinator in lambda calculus.

Usage

import { composition } from '@accelint/core';

// Compose two functions
const result = composition((x: number) => x + 8)((x: number) => x * 3)(4);
// 20 (4 * 3 = 12, 12 + 8 = 20)

// Partial application
const multiplyThenAdd = composition((x: number) => x + 10);
multiplyThenAdd((x: number) => x * 2)(5); // 20

Reference

function composition<A, B>(
  f: (z: A) => B
): <C>(g: (y: C) => A) => (x: C) => B

Lambda calculus: λabc.a(bc)
Type signature: composition :: (a → b) → (c → a) → c → b

Parameters

ParameterTypeDescription
f(z: A) => BThe second function in the composition (applied last).
g(y: C) => AThe first function in the composition (applied first).
xCThe value to pass to g.

Returns

Returns the result of f(g(x)).

Type Parameters

  • A - The return type of g and input type of f
  • B - The return type of f
  • C - The input type of g

Examples

Example: Data transformation

import { composition } from '@accelint/core';

const trim = (s: string) => s.trim();
const toUpperCase = (s: string) => s.toUpperCase();

const trimAndUpper = composition(toUpperCase)(trim);
trimAndUpper('  hello  '); // 'HELLO'

Example: Mathematical operations

import { composition } from '@accelint/core';

const square = (x: number) => x * x;
const increment = (x: number) => x + 1;

// Square then increment
const squareThenInc = composition(increment)(square);
squareThenInc(5); // 26 (5² = 25, 25 + 1 = 26)

// Increment then square
const incThenSquare = composition(square)(increment);
incThenSquare(5); // 36 (5 + 1 = 6, 6² = 36)

Example: Object transformations

import { composition } from '@accelint/core';

interface User {
  firstName: string;
  lastName: string;
}

interface FullName {
  fullName: string;
}

const getFullName = (u: User): string =>
  `${u.firstName} ${u.lastName}`;

const toNameObject = (name: string): FullName => ({ fullName: name });

const transform = composition(toNameObject)(getFullName);

const user: User = { firstName: 'John', lastName: 'Doe' };
transform(user); // { fullName: 'John Doe' }

Example: Validation pipeline

import { composition } from '@accelint/core';

const isNotEmpty = (s: string): boolean => s.length > 0;
const hasMinLength = (min: number) => (s: string): boolean => s.length >= min;

// Check string after trimming
const validateAfterTrim = (min: number) =>
  composition(hasMinLength(min))((s: string) => s.trim());

validateAfterTrim(3)('  ab  '); // false (trimmed length is 2)
validateAfterTrim(3)('  abc  '); // true (trimmed length is 3)

Good to know: This combinator applies functions right-to-left (f(g(x))). For left-to-right composition, use pipe. For composing more than two functions, use compose.

  • pipe - Compose functions left-to-right
  • compose - Compose multiple functions right-to-left
  • apply - Apply function to value

On this page