liveBook · Manning

Compositionality

As explained in Functional Programming in Scala, Second Edition

Compositionality is the property that components can be combined generically to form larger computations without depending on their internal implementations.

Compositionality means combining components into larger computations without inspecting their internal implementations. In parallel programming, this requires meaningful values and operations that compose rather than side effects or blocking control flow. section 7.1.1

Concurrency APIs differ in how well they support generic composition:

  • Runnable returns Unit, so extracting results requires side effects and knowledge of internal behavior. section 7.1.1
  • Future abstracts physical threads but exposes blocking get and no compositional API for combining computations. section 7.1.1
  • A Par data type represents parallel computations as values, allowing larger computations to be assembled from smaller ones. section 7.1.1
Listing 7.2 Updating sum with our custom data type
def sum(ints: IndexedSeq[Int]): Int =
  if ints.size <= 1 then
    ints.headOption.getOrElse(0)
  else
    val (l, r) = ints.splitAt(ints.size / 2)
    val sumL: Par[Int] = Par.unit(sum(l))      #1
    val sumR: Par[Int] = Par.unit(sum(r))      #2
    Par.get(sumL) + Par.get(sumR)              #3

The recursive sum example shows composition concretely: split the input, wrap each subcomputation with Par.unit, and retrieve their results with Par.get. section 7.1.1

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Defines the principle through Runnable, Future, and Par contrasts, but defers the underlying implementation details.
Examples
Uses recursive parallel sum, Par.unit, Par.get, Runnable, Future, and ExecutorService as concrete examples.
What you can do after
Apply it via a Par data type to assemble recursive parallel computations from explicit subcomputation values.
How it connects
Connects functional programming with concurrency, parallel computation, Runnable, Future, and ExecutorService.

Also explained in

Compare how 2 books explain compositionality →

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.