Combinable — Combining Values
Aggregating collections of data is a fundamental task in software engineering. Summing an array of invoice prices, concatenating list items into a single string, or merging a series of configuration profiles are structurally identical operations.
In JavaScript, our standard tool for this is Array.prototype.reduce. While powerful, reduce
forces us to explicitly supply both the combining callback and the initial starting value at every
single call site:
This leads to redundant, repetitive ceremony. If we want to sum numbers, we must write
(acc, x) => acc + x and 0. If we want to multiply numbers, we must write (acc, x) => acc * x
and 1. The combining logic and the starting value are decoupled, forcing the developer to track
both separately.
Combinable<A> packages these two related concerns into a single, reusable data structure:
emptyis the neutral starting element. Combining any value withemptyyields the original value unchanged.combineis the data-last combining operation, taking the next element and appending it to the accumulated value.
In abstract algebra, this combination is known as a Monoid. By packaging the baseline value and the appending logic into a first-class blueprint, we get a highly reusable, clean strategy for collection aggregation.
Built-In Aggregators
Section titled “Built-In Aggregators”The library provides optimized, built-in combiners for standard primitives:
Notice the numbers example. Summation and multiplication are both mathematically valid ways to
combine numbers, but they require different baseline elements (0 for sum, 1 for product). By
using Combinable.sum or Combinable.product, we make our exact aggregation intent explicit in our
code.
Folding Collections point-free: fold
Section titled “Folding Collections point-free: fold”Combinable.fold accepts a Combinable<A> and returns a clean, single-argument function
(as: A[]) => A that collapses an array into a single value:
Combining Optional Values: maybe
Section titled “Combining Optional Values: maybe”Often, the values we want to combine are optional, represented by Maybe<A>. Combinable.maybe
lifts a Combinable<A> to operate safely over Maybe<A> values:
This makes folding collections of optional domain fields extremely elegant:
Problems it solves
Section titled “Problems it solves”- Aggregating distributed telemetry and metric reports: In telemetry and reporting services,
merging multiple event payloads (such as summing total request counts, combining latency tallies,
and aggregating error counts) often requires repetitive reducer loops.
Combinable.structcombines complex metric records automatically based on field-level rules. - Hierarchical configuration merging: In applications loading layered configurations (such as
default settings overlaid with environment variables and tenant-specific overrides),
Combinable.recordmerges configuration layers cleanly while preserving immutability. - Aggregating sparse or optional metrics (
Combinable.maybe): Folding streams of optional data (such as user ratings or partial session durations) where missing values (None) are safely ignored while valid numbers are accumulated. - Reusable collection reduction strategies: Instead of re-writing
Array.prototype.reducecallbacks with manual initial values across multiple call sites,Combinableprovides named, reusable aggregation strategies (Combinable.sum,Combinable.concat,Combinable.maybe) for point-free list folding.