liveBook · Manning

foldMap

As explained in Functional Programming in Scala, Second Edition

foldMap transforms the elements of a data structure and combines the results using the operations of a monoid, discarding the original structure.

foldMap transforms each element into a value that can be combined, then discards the original structure. Its result type need not match the element type: a list of values becomes one B by applying A => B and combining the mapped values with a Monoid[B]. The monoid supplies both combine and the empty result for an empty input. section 10.2 section 10.9

def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B

The core API separates the input element type A from the mapped result type B, requiring a Monoid[B] to combine results. section 10.2

A direct List implementation starts with m.empty and, for each element a, combines the accumulator with f(a). This is the map-then-reduce pattern expressed without constructing an intermediate mapped list. Associativity and identity mean an implementation may use either foldLeft or foldRight without changing the result. section 10.2 section 10.9

Mapping values into a result

To concatenate transformed elements, map each element to a String and use string concatenation's empty string and combine operation. The same shape supports addition, multiplication, Boolean conjunction or disjunction, and list concatenation by choosing a different Monoid. section 10.2 section 10.9

For IndexedSeq, foldMapV splits the sequence in half, recursively folds each half, and combines the two results. A balanced fold avoids repeatedly allocating ever-larger intermediate strings. The same associativity also permits a parallel version: lift a Monoid[A] into Monoid[Par[A]], map elements in parallel, and combine their results. section 10.3 section 10.9

foldMap also exposes folding as a reusable abstraction:

  • foldLeft and foldRight can be derived by mapping elements to endofunctions and combining them with function composition; foldRight needs the dual composition order. section 10.9
  • Foldable gives foldMap, foldLeft, foldRight, and combineAll to structures including List, IndexedSeq, LazyList, Tree, and Option. section 10.9 section 10.9
  • A map-valued Monoid can turn an IndexedSeq into a bag by mapping every element to a singleton count map. section 10.9
  • Traverse can express foldMap through a constant applicative built from a Monoid. section 12.7.1

Checking ordered input

Map each integer to interval information, then combine adjacent intervals with a Monoid that records whether ordering still holds. foldMapV reduces the sequence to an optional interval and returns its ordered flag, or true for an empty sequence. section 10.3 section 10.9

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Works through List implementation, derived left and right folds, balanced IndexedSeq folding, and parallel reduction.
Examples
Uses string concatenation, balanced string folding, ordered integer sequences, word counting, and bags represented as maps.
What it assumes
Assumes Scala collections and functions while grounding combination in a Monoid's combine and empty operations.
What you can do after
Build it from scratch for lists and indexed sequences, including balanced and parallel variants.
How it connects
Connects Monoid, foldLeft, foldRight, Foldable, parallelism, Traverse, Applicative, and Functor.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.