#readwise
# From Design Patterns to Category Theory

## Metadata
- Author: [[Mark Seemann]]
- Full Title: From Design Patterns to Category Theory
- URL: https://blog.ploeh.dk/2017/10/04/from-design-patterns-to-category-theory/
## Summary
From Design Patterns to Category Theory is a blog series that covers various topics from category theory.
Here's a list of articles that belong to this series, retrieved on March 17, 2023:
- [[Monoids, Semigroups, and Friends]]
- [[Functors, Applicatives, and Friends]]
- Software design isomorphisms
- Unit isomorphisms
- Function isomorphisms
- Argument list isomorphisms
- Uncurry isomorphisms
- Object isomorphisms
- Abstract class isomorphism
- Inheritance-composition isomorphism
- Tester-Doer isomorphisms
- Builder isomorphisms
- Church encoding
- Church-encoded Boolean values
- Church-encoded natural numbers
- Church-encoded Maybe
- Church-encoded Either
- Church-encoded payment types
- Church-encoded rose tree
- Catamorphisms
- Boolean catamorphism
- Peano catamorphism
- Maybe catamorphism
- List catamorphism
- Either catamorphism
- Tree catamorphism
- Rose tree catamorphism
- Full binary tree catamorphism
- Payment types catamorphism
- Some design patterns as universal abstractions
- Composite as a monoid
- Coalescing Composite as a monoid
- Endomorphic Composite as a monoid
- Null Object as identity
- Builder as a monoid
- Visitor as a sum type
- Chain of Responsibility as catamorphisms
- The State pattern and the State monad
- Refactoring the TCP State pattern example to pure functions
- Refactoring a saga from the State pattern to the State monad
- Postel's law as a profunctor
- The Liskov Substitution Principle as a profunctor
- Backwards compatibility as a profunctor
## Highlights
With such abstractions, source code becomes easier to understand. Like everything else, there's no silver bullet, but **good coding abstractions can save you much grief, and make it easier to understand big and complex code bases. ==Not only can a good abstraction shield you from having to understand all the details in a big system, but if you're familiar with the abstraction, you may be able to quickly get up to speed==.** While the above definition is great for identifying a good abstraction, it doesn't tell you how to create one.
---
**Design patterns are useful in two ways:**
- ==**They offer solutions**==
- **==They form a vocabulary==**
---
In my opinion, however, people often overlook the second advantage. Programmers are often eager to find solutions. "I have a problem; what's the solution? Oh, here's a design pattern that fits!"
---
I have no problems with ready-made solutions, but I think that the other advantage may be even bigger. **When you're looking at unfamiliar source code, you struggle to understand how it's structured, and what it does. ==If, hypothetically, you discover that pieces of that unfamiliar source code follows a design pattern that you know, then understanding the code becomes much easier.==**
---
There are two criteria for this to happen:
- The reader (you) must already know the pattern
- The original author (also you?) must have implemented the pattern without any surprising deviations
---
As a programmer (code author), you can **help readers (users) of your code. Don't use every design pattern in the book, but when you use one, make it as obvious to the reader as you can: Use the terminology, class names, and so on from the book**. Add comments where your naming deviates. Add links that the novice user can follow to learn more.
---
Design Patterns was a great effort in 1994, and I've personally benefited from it. The catalogue was an attempt to discover good abstractions. What's a good abstraction? As already quoted, it's a model that amplifies the essentials, etcetera. I think a good abstraction should also be intuitive.
---
**Writers before me have celebrated the power of mathematical abstraction in programming.** For instance, in Domain-Driven Design Eric Evans discusses how Closure of Operations leads to object models reminiscent of arithmetic. **If you can design Value Objects in such a way that you can somehow 'add' them together, you have an intuitive and powerful abstraction.**
---
**Notice that there's more than one way to combine numbers. You can add them together, but you can also multiply them. Could there be a common abstraction for that?** What about objects that can somehow be combined, even if they aren't 'number-like'? **The generalisation of such operations is a branch of mathematics called category theory**, and it has turned out to be productive when applied to functional programming. Haskell is the most prominent example. ^9dk84j
---
'things' in category theory are called objects, and while they aren't objects in the sense that we think of in object-oriented design, there is some equivalence. **Category theory concerns itself with how objects map to other objects**. A functional programmer would interpret such morphisms as functions, but in a sense, you can also think of them as well-defined behaviour that's associated with data.
---
**objects of category theory are universal abstractions. Some of them, it turns out, coincide with known design patterns. The difference is, however, that ==category theory concepts are governed by specific laws==. In order to be a functor, for example, an object must obey certain simple and intuitive laws. ==This makes the category theory concepts more specific, and less ambiguous, than design patterns==.**
---
I believe that **==learning about these universal abstractions is the next step in software design. If you know design patterns, you have a vocabulary, but the details are still open to interpretation. If you know category theory, you have a better vocabulary==. Just like design patterns, you have to learn these things, but once you've learned them, you've learned something that transcends a particular software library, a particular framework, a particular programming language. Learning about functors, monoids, and so on, is a good investment, because these concepts are rooted in mathematics, not any particular technology.** ^8hzxnf
---
**Object-oriented programming (OOP) is the dominant software design paradigm. It wasn't always so. When OOP was new, many veteran programmers couldn't see how it could be useful.** They were schooled in one paradigm, and it was difficult for them to shift to the new paradigm. **They were used to do things in one way (typically, procedural), and it wasn't clear how to achieve the same goals with idiomatic object-oriented design. The same sort of resistance applies to functional programming.** Tasks that are easy in OOP seem impossible in functional programming. How do you make a for loop? How do you change state? How do you break out of a routine? **This leads to both frustration, and dismissal of functional programming, which is still seen as either academic, or something only interesting in computation-heavy domains like science or finance.**
---