I’m thinking about modularity again. In particular, I’m thinking about the formally-pure mathematical notion of compositionality:
Compositionality is the principle that a system should be designed by composing together smaller subsystems, and reasoning about the system should be done recursively on its structure.
(Jules Hedges, On Compositionality)
This sounds pretty similar to the definitions of modularity we roughed out in The Internet is Modular. There is a key distinction, though. A modular system is compositional when you can compose modules without side-effects. In a compositional system, the whole is exactly the sum of its parts.
Compositionality helps us reason at scale
If a system is to serve the creative spirit, it must be entirely comprehensible to a single individual. The point here is that the human potential manifests itself in individuals. (Alan Kay, 2001. Design Principles Behind SmallTalk.)
Problems are solved by people, and that means we need people-sized problems. A challenge here is that our brains are pretty small, and many problems are big.
One trick we’ve learned to scale our efforts is to break problems down into smaller units, until the units are roughly person-sized. If the whole is exactly the sum of the parts—or close-enough—then we can solve them one at a time. Add more people, and we can solve them in parallel. MapReduce!
Even better, when systems are compositional, we can use tools like category theory to formally reason about them. This is very powerful.
I claim that compositionality is strictly necessary for working at scale. In a non-compositional setting, a technique for a solving a problem may be of no use whatsoever for solving the problem one order of magnitude larger.
(Jules Hedges, On Compositionality)
So, we could see compositionality as a constraint we sometimes impose upon systems to scale our reasoning. Like other reductionistic methods, compositionality asks us to narrow the expressive range of motion of a system, in order to gain rational leverage.
Certain forms of knowledge require a narrowing of vision... bringing into focus limited aspects of a complex, unwieldy reality. This simplification makes [reality] legible and susceptible to measurement and calculation, making possible a high degree of schematic knowledge, control, and manipulation.
(James C Scott, 1998. Seeing Like a State.)
This is a clever trick, and we’ve gone pretty far with it, building machines and bridges and computers and all sorts of other things.
Compositionality rejects emergence
A wrinkle. Compositionality only works when a system is exactly the sum of its parts.
More generally, I claim that the opposite of compositionality is emergent effects. The common definition of emergence is a system being “more than the sum of its parts”, and so it is easy to see that such a system cannot be understood only in terms of its parts, i.e. it is not compositional. Moreover I claim that non-compositionality is a barrier to scientific understanding, because it breaks the reductionist methodology of always dividing a system into smaller components and translating explanations into lower levels. (Jules Hedges, On Compositionality)
When the system is exactly the sum of its parts, you can take the system apart, reason about each part separately. But when the whole is more than the sum of its parts?
If you try and take a cat apart to see how it works, the first thing you have on your hands is a non-working cat. (Douglas Adams)
A lot of systems are like cats. Maybe even most of them—definitely all of the living ones. In a living system, the emergence is the point.
We call these emergent systems complex adaptive systems. As David C. Krakauer points out, our reductive engineering tricks come up short when confronted with these complex systems.
The Properties of Complex Systems
1. We have few general design principles for adaptive components (cells, organisms, nations) in isolation or in the aggregate where new unforeseen properties emerge.
2. Components typically have high failure rates in all tasks and accomplish their objectives through statistical averaging and approximation across multiple scales and levels.
3. There is significant uncertainty and lack of information at both the component and aggregate level, and components have large—and often poorly understood—repertoires of behavior.
4. Most evolved complex systems operate in nonlinear and often near-critical regimes (close to thresholds and tipping points).
5. Adaptability of components is the rule—not the exception—and learning and adaptation are ongoing and irrepressible.
Nearly every assumption listed in the engineering axioms is violated by complex systems. So, what leads us to believe that we can use the insights of classical engineering to predict and control these systems? And the recent historical record makes the case rather clear—we have not succeeded in this approach.
(David C. Krakauer, 2019. Emergent Engineering.)
Well, and all evolving systems have these characteristics. Think biology. Squishy, redundant, interconnected, nonlinear. Emergence defies our reductive methods.
Only that which can change can continue (James Carse)
And you may not like it, but this is what peak performance looks like. Evolving systems are resilient, adaptive, generative, alive. So I’m personally interested in building more evolvable systems that provoke emergence.
Then what are we to do with compositionality? Can we scale our reasoning without producing a non-working cat?
Modularity enables emergence
This story gets even more nuanced when we recall that modularity enables evolution. From The Internet is Modular:
Long before DNA was discovered, it was known that the mechanism of heredity behind biological evolution must be digital, countable, modular. Why? Evolution happens in any system with mutation, heredity, selection, and you can’t have mutation unless it is possible to add and remove parts—modularity! So, modularity is a key attribute of evolving systems.
So this can’t be reduced down to modularity = good/bad. Instead, we have two closely-related concepts, modularity and compositionality. They are nearly indistinguishable, but have radically different implications.
Both are recursively composed from smaller units.
Both have boundaries, and encourage us to treat them as black boxes.
Both are loosely coupled through interfaces.
Modular systems admit side-effects. Compositional systems do not.
That small difference makes a big difference. Modular systems can evolve, compositional systems cannot.
When designing a system, it is important to understand which we are after.
Compositional components, emergent protocols
The best material model of a cat is another, or preferably the same, cat.
(Norbert Wiener)
Our dilemma: we want living systems, but we only know how to reason about dead ones. Where does this leave us vis-a-vis non-working cats? I’m not sure. Smart people are trying to work that out. But I have a notion for a makeshift approach that may work in software ecosystems for the time-being:
Components should be compositional.
Protocols should provoke emergence.
Components should be compositional. Right now, compositional components are the only way we know to build reliable software at scale. That means large parts of our systems must be built with compositional building blocks. We just don’t know any other way (yet). Tools like Rust can help us craft more reliable software with fewer unintended side-effects.
On the other hand, protocols should provoke emergence. All of the interesting systems are emergent. Biology, economies, language, the internet, technology, culture. These evolving ecosystems are the only kind that can continually produce innovation.
The role of a protocol should be to present an interface for generating interesting side-effects together!
A story—in the beginning, the web didn’t have any side-effects. HTTP is a stateless protocol. You ask for a document, you get it. You ask for the same document, you get it again. Useful, but dull.
What really made the web kick off was the invention of CGI-scripts. CGI enabled servers to interact with the user, remember what happened, and dynamically respond to requests. Side-effects! This simple mechanism made possible the invention of forums, e-commerce, social media, web apps, the works.
Note that HTTP itself is stateless, but the architecture has space at the edge for stateful endpoints that can remember and dynamically respond. This capacity for memory and dynamic feedback is what we need to provoke emergence. In fact, feedback is memory, because the next state is the recursive result of previous states. Feedback is all you need to provoke emergence. Once it’s in the mix, the whole is no longer the sum of the parts. Instead, it is the emergent outcome of internal processes and personal history.
So, my takeaway is that memory and feedback belong somewhere at the edge of the protocol architecture, where users and developers live.
Anyway, this is what I’m thinking about while we’re building a protocol for thought.