Lesson 10 / 25

Function Composition and Pipelines

compose and pipe.

Joining functions end to end

Composing f and g gives a new function x => f(g(x)): apply g, then f. compose(f, g, h) applies functions right to left, matching mathematical notation; pipe(h, g, f) applies them left to right, which usually reads better. Composition works best with unary functions whose output type matches the next input type. Libraries such as Ramda, lodash/fp and fp-ts provide these helpers; a JavaScript pipeline operator |> has been proposed but is not part of the language at the time of writing, so check the TC39 proposal status. In Haskell, composition is the built-in . operator.

Building big functions from small ones

Composition connects the output of one function to the input of the next, so programs read as pipelines.

Three ideas: compose and pipe, currying and partial application, point-free style.
Figure 4.1 — Small functions joined into a pipeline.

A tiny pipe helper

Typed for a uniform type to keep the example short.

const pipe = <T>(...fns: Array<(x: T) => T>) =>
  (x: T): T => fns.reduce((acc, fn) => fn(acc), x);

const compose = <T>(...fns: Array<(x: T) => T>) =>
  (x: T): T => fns.reduceRight((acc, fn) => fn(acc), x);

const trim = (s: string) => s.trim();
const lower = (s: string) => s.toLowerCase();
const collapseSpaces = (s: string) => s.replace(/ +/g, ' ');

const normalise = pipe(trim, lower, collapseSpaces);
// normalise('  Hello   World ') evaluates to 'hello world'

const normalise2 = compose(collapseSpaces, lower, trim); // same result

Composition in Haskell

Haskell composes with the built-in . operator, right to left: normalise = map toLower . unwords . words splits on whitespace, rejoins with single spaces, then lowercases (with toLower imported from Data.Char).

Quick check: In what order does `pipe(a, b, c)(x)` apply the functions?

  • `a` first, then `b`, then `c`
  • `c` first, then `b`, then `a`
  • All three in parallel
  • Only `a`; the others are ignored
Answer

`a` first, then `b`, then `c` — pipe reads left to right; compose reads right to left.