FooCafe
Mainstream language designers delayed functional features for decades by avoiding mathematics, only to unconsciously replicate category theory's exponential objects in Java 8 and make monads structurally inevitable.
AI-assisted summary of Category Theory, The essence of interface-based design - Erik Meijer — original source. Check the original for full context.
Source published:
Key ideas
- Erik Meijer argues that mainstream programming language features mirror mathematical discoveries made decades earlier, noting that Java 8 method references and lambdas precisely recreate the Cartesian closed categories formalized by Joachim Lambek and Alonzo Church. (0:00)
- Software developers routinely practice category theory through interface-based design and the Curry-Howard isomorphism, where types act as theorems, programs serve as proofs, and category-theoretic objects and morphisms map directly to types and static methods. (8:14)
- Instance methods do not exist at the fundamental machine or categorical level; as early as 1979 in C++ and in the JVM specification, instance methods are simply static functions where the instance reference 'this' is passed as the implicit first argument. (49:41)
- Because Java 8 introduced exponential objects via method references (such as 'a::m' yielding a 'Function<B, C>'), it inherently incorporated categorical adjunctions, making monads like the State monad a structural inevitability in mainstream languages. (58:37)
Detailed notes
## Background Published by FooCafe on YouTube on September 10, 2015, this video features a presentation by Erik Meijer at Foo Café in Malmö/Lund. The session explores how category theory serves as the mathematician's interpretation of interface-based design, illustrating how modern object-oriented language features like Java 8 lambdas and method references embody Cartesian closed categories originally formalized decades ago by thinkers like Joachim Lambek.
## TL;DR Erik Meijer urges software developers to overcome their math aversion and actively borrow conceptual tools from category theory to improve their API design and careers. He systematically maps abstract mathematical constructs—categories, objects, morphisms, products, and functors—to everyday programming notions like languages, types, static methods, tuples, and generics. Meijer demonstrates that mainstream object-oriented mechanisms, such as Java 8 method references and instance method dispatch, are practical manifestations of categorical exponential objects and currying. Because exponential objects form adjoint functors, he concludes that the adoption of lambdas makes monads structurally inevitable in the future of mainstream programming languages.
## Atmosphere & style The presentation is lively, irreverent, and thoroughly engaging, driven by Meijer's animated delivery, self-deprecating humor, and sharp wit. Rather than delivering a dry academic lecture, Meijer constantly banters with the audience, cracking jokes about drinking beer, poking fun at purist Haskell programmers, and advising developers to use mathematical jargon to negotiate higher salaries. The atmosphere blends accessible technical intuition with intellectual enthusiasm, making dense categorical diagrams feel practical, approachable, and fun.
## Bulletin - [00:00](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=0s) Erik Meijer argues that mainstream programming language features mirror mathematical discoveries made decades earlier, noting that Java 8 method references and lambdas precisely recreate the Cartesian closed categories formalized by Joachim Lambek and Alonzo Church. - [08:14](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=494s) Software developers routinely practice category theory through interface-based design and the Curry-Howard isomorphism, where types act as theorems, programs serve as proofs, and category-theoretic objects and morphisms map directly to types and static methods. - [49:41](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2981s) Instance methods do not exist at the fundamental machine or categorical level; as early as 1979 in C++ and in the JVM specification, instance methods are simply static functions where the instance reference 'this' is passed as the implicit first argument. - [58:37](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3517s) Because Java 8 introduced exponential objects via method references (such as 'a::m' yielding a 'Function<B, C>'), it inherently incorporated categorical adjunctions, making monads like the State monad a structural inevitability in mainstream languages.
## Key takeaways - [00:00](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=0s) Language designers and developers frequently reinvent theoretical concepts decades late because they neglect deliberate continuous learning and avoid dense mathematical research. - [01:50](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=110s) Leslie Lamport advocates that software developers should embrace mathematics just as civil engineers and chemists do, rather than fearing it. - [04:44](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=284s) Developers are alienated by bottom-up mathematical pedagogy and obscure notation, whereas programming is effectively learned top-down through concrete problem-solving. - [08:14](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=494s) Category theory and interface-based design share the same core abstraction: studying the structural form of systems entirely decoupled from their underlying content. - [08:14](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=494s) Under the Curry-Howard isomorphism, types represent mathematical theorems and programs represent the constructive proofs of those theorems. - [08:14](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=494s) The core primitives of category theory map directly to software: a category corresponds to a programming language, objects correspond to types, and morphisms represent methods or functions. - [14:46](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=886s) Categorical products define compound types (tuples) equipped with projection functions and equational behavioral laws, which typical OOP interfaces fail to enforce. - [19:35](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1175s) OOP interfaces only specify type signatures, leaving them vulnerable to trivial, broken implementations (such as returning null) that violate behavioral contracts. - [25:03](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1503s) Alonzo Church formalised tuples in the lambda calculus in 1928 and John McCarthy built them in Lisp in 1960, yet mainstream languages like Java went decades without first-class tuple support. - [28:07](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1687s) Object-oriented programming does not actually model the physical world; software deals purely with abstract in-memory data representations and mathematical structures. - [31:31](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1891s) Reflection is an awkward meta-level workaround for treating methods as first-class values, a problem solved cleanly by Smalltalk blocks and category-theoretic exponentials. - [34:43](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2083s) Categorical exponentials (Z^Y) represent function spaces based on combinatorics, though impure side effects in imperative languages break mathematical function counting. - [41:56](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2516s) In typed languages, a functor is a generic type constructor equipped with a map operation that preserves identity and function composition. - [49:41](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2981s) JVM bytecode demonstrates that instance methods are merely static procedures with the 'this' reference stored at local variable index zero. - [53:35](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3215s) Java 8 method references (a::m) are direct implementations of category-theoretic exponential objects and evaluation morphisms. - [58:37](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3517s) Currying and uncurrying represent the natural isomorphism between product morphisms Hom(X × Y, Z) and exponential morphisms Hom(X, Z^Y). - [58:37](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3517s) Because exponential objects form adjoint functors, adopting them in Java 8 structurally guarantees that monads will inevitably become explicit in mainstream OOP languages.
## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=0s) Celebrating Foo Café and Joachim Lambek
Erik Meijer opens the session celebrating the three-year anniversary of Foo Café alongside a tribute to mathematician Joachim Lambek. Lambek is celebrated among category theorists for establishing the fundamental connection between the lambda calculus and category theory. Meijer jokingly points out the uncanny coincidence in their naming: “funnily his name kind of you know has the same prefix as the lambda calculus, isn't that a coincidence I don't know.”
Framing the evening under the theme of deliberate and continuous learning, Meijer polls the audience on who is running Java 8 versus older releases like Java 6. Seeing the divide, he notes how many years it dragged on before Java introduced lambda expressions. He argues that if programming language designers practiced deliberate and continuous learning, these features would have arrived decades earlier, because researchers like Lambek had already laid down the theoretical foundations. His goal for the talk is practical and mercenary: “tonight I'm going to tell you the tricks how you as a developer can tap into the brains of mathematicians and kind of steal their ideas such that you know you can kind become a better developer and then go to your boss and ask for more money because you're an awesome developer.”
[01:50](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=110s) The Pain of Language Specs and Leslie Lamport's Advice
Meijer confesses to an unusual hobby: reading programming language specifications cover to cover. While other people read novels or newspapers, he collected manuals stretching back through early Lisp 1.0, Pascal, Visual Basic, C#, ECMAScript, Swift, and Dart. Yet, despite his high tolerance for dense specifications, Java 8 broke him: “there's one language specification that even for me was too strong it was impossible to read and that language specification is Java 8.” He jokes that if you suffer from insomnia, opening the Java Language Specification works better than any sleeping pill. The complexity surrounding Java 8's method references, in particular, proved unnecessarily opaque.
When faced with overwhelming engineering complexity, Meijer turns to the philosophy of Turing Award winner Leslie Lamport. Lamport advocates that software developers ought to incorporate more mathematics into their everyday thinking. While mechanical and civil engineers routinely rely on math to build bridges, and chemists lean on it daily, software engineers remain strangely math-averse. Meijer insists developers must shed that fear.
```mermaid flowchart LR accTitle: Lamport's Prescription for Software accDescr: Comparing how traditional engineering fields use math versus computer science. subgraph Traditional["Traditional Engineering"] CE["Civil Engineers\n(Bridges)"] --> M1["Use Mathematics"] CH["Chemists\n(Reactions)"] --> M1 end subgraph Computing["Computer Science"] SE["Software Developers"] -.->|"Fear / Avoid"| M2["Mathematics"] LL["Leslie Lamport's Advice"] ==>|"Prescribes"| SE SE ==>|"Must Embrace"| M2 end ```
[04:44](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=284s) Why Developers Fear Mathematics: The Pedagogy Problem
Meijer breaks down why software engineers are intimidated by mathematics, validating that their reservations stem from real systemic flaws in how math is communicated and taught:
- Math textbooks are notoriously poor; the notation is obscure and “doesn't even type check.” - The jargon and terminology are alienating, quickly dragging the reader down a rabbit hole filled with “Greek symbols and other dirty pictures.” - Math is almost exclusively taught bottom-up: students must digest endless abstract machinery before ever getting to see a concrete application.
By contrast, programming is taught top-down. Polling the audience reveals that only about half hold a formal computer science degree. Those without a degree never started by grinding Big-O notation or Turing machines; they opened an editor, began hacking to solve an immediate problem, and acquired theory on a need-to-know basis as they ran into deeper challenges.
Meijer illustrates this pedagogical failure with linear algebra. Most university courses introduce linear algebra through the mechanical, tedious manipulation and multiplication of matrices for graphics. Yet at its conceptual core, an $m \times n$ matrix is simply the concrete data representation of a linear function mapping a sequence of length $n$ to a sequence of length $m$, and matrix multiplication is nothing other than standard function composition. He laments that students are forced to write the equivalent of raw assembly: “This is completely nonsense that we as humans have to do that if instead they would teach linear algebra as a restricted form of functional programming with some special functions that are linear which means that they have nice properties everything would be easy.” Because mathematicians insist on bottom-up explanations, developers are left scratching their heads wondering why any of it matters.
[08:14](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=494s) Abstract Nonsense, Interface-Based Design, and Curry-Howard
Even professional mathematicians look at category theory and jokingly dismiss it as "abstract nonsense." This label exists because proofs within category theory operate at extreme altitude, described formally as: “the study of the general form of mathematical theories without regard to their content.” In this realm, concrete intuition is deliberately stripped away in favor of skeletal form.
Meijer contends that software developers already practice this exact mindset every day through interface-based design: - When writing code against an abstract interface rather than a concrete implementation class, developers program “without regard to their content.” - The identical calling program works unaltered regardless of which concrete type is supplied underneath. - Software design patterns function in the exact same abstract manner; few people actually read the *Design Patterns* book cover-to-cover because its patterns are completely decoupled from specific business logic, existing instead as general reusable structural templates.
```mermaid flowchart TD accTitle: Correspondence between Math and Programming Concepts accDescr: Mapping abstract category theory concepts directly to everyday object-oriented software practices. subgraph MathTheory["Mathematical Abstraction"] ABS["Study form without content"] THM["Theorems"] PRF["Proofs"] CAT["Category"] end subgraph SoftwarePractice["Software Engineering"] INT["Interfaces & Design Patterns"] TYP["Types"] PRG["Programs / Code"] LAN["Programming Language"] end ABS <-->|"Isomorphism"| INT THM <-->|"Curry-Howard"| TYP PRF <-->|"Curry-Howard"| PRG CAT <-->|"Direct Analogy"| LAN ```
Meijer connects this directly to proof theory via the Curry-Howard isomorphism, which he describes as one of the most elegant concepts in computing: “Curry-Howard isomorphism says that a type is a theorem and the program is the proof for that theorem.” Under this lens, developers writing code are continually constructing proofs of mathematical theorems, meaning developers and mathematicians are engaged in the same discipline—except mathematicians simply program far more slowly, sometimes spending decades to produce a tiny proof.
Moving toward category theory itself, Meijer demystifies its intimidating reputation, stating that the entire system is built upon three remarkably simple building blocks: - A **Category**, which directly corresponds to an entire **Programming Language**. - **Objects**, which directly correspond to the language's **Types** (such as booleans, strings, and lists in Java). - **Morphisms**, which represent the arrows, functions, and transformations connecting those types.
[12:52](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=772s) Morphisms as Static Methods and the Language Bold 3
Erik Meijer clarifies that the mathematical term *morphism* is just an unnecessarily fancy name for a concept everyday programmers already know: “a morphism from A to B is just a static method that takes a argument of type A and returns a value of type B or equivalently you can say it's a property.” A developer might naturally object: if this is meant to model modern object-oriented programming, why restrict the definition to static methods instead of instance methods? Meijer notes that while instance methods will be addressed later, the foundational goal of the talk is to establish precision, pinning down the mathematical machinery so that category-theoretic concepts map directly to concrete language features.
```mermaid flowchart LR accTitle: Category Bold 3 Schema accDescr: Three types A, B, and C with arrows representing functions between them. subgraph Bold3["Category / Language: 3"] A["Type A (e.g. Character)"] B["Type B (e.g. Integer)"] C["Type C (e.g. Boolean)"] C -->|"f"| A A -->|"g"| A end ```
To demonstrate how mathematicians operate, Meijer points out that they resemble exceptionally slow programmers. He presents a toy category known in mathematics as the category **3** (or "bold three"). It represents a tiny programming language consisting of exactly three types—conceptually analogous to characters, integers, and booleans—and a few defined functions running between them, such as a function from booleans to characters, or a function from characters back to characters. For category theorists, a construct as minimal as three types and a couple of arrows is so monumental that they publish papers on it and give it a dedicated name. Meijer jokes that if someone tried to draw the equivalent full graph for all the types and methods in Java, the diagram would spill off the slides, cover all the walls of the venue, and fill the entire city like a massive graffiti art installation. Yet mathematicians take pride in fully understanding their tiny three-type world.
[14:46](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=886s) Tuples, Category-Theoretic Products, and Android Libraries
Once a language has basic types, developers invariably want to combine them into compound types. In modern programming, practically everyone demands tuples. Java itself lacks built-in language support for tuples, forcing developers to rely on third-party libraries. Meijer asks the audience if anyone develops for Android (or perhaps Windows Phone), noting that the standard Android SDK explicitly includes a tuple utility type because tuple pairs are essential even on a mobile phone.
He then displays the standard category-theoretic definition of a product: a formal definition heavy with phrases like "commuting diagrams," "canonical morphisms," and "universal properties." Anticipating the audience's dread, Meijer jokes, “you will ask yourself oh my goodness where's my beer the next beer this looks kind of horrible.” To demystify the intimidating Greek symbols and formal terminology, he breaks the text down clause by clause into ordinary programming concepts: - A category $C$ corresponds to a programming language. - Objects $X_1$ and $X_2$ correspond to types. Meijer specifically prefers the word "types" rather than "objects" to avoid ambiguity, because in object-oriented programming people constantly conflate classes, types, and object instances. - Forming a product $X_1 \times X_2$ corresponds to creating a tuple type `(X1, X2)` or a pair.
```mermaid flowchart TD accTitle: Universal Property of a Category Product accDescr: Commuting diagram showing projections pi 1 and pi 2 from product X to objects X1 and X2, along with morphisms f and g from an arbitrary object C factored through a unique pair morphism. C["Source Object / Type: C"] Prod["Product Type: X (X1 × X2)"] X1["Type: X1"] X2["Type: X2"]
Prod -->|"π₁ (fst / _1)"| X1 Prod -->|"π₂ (snd / _2)"| X2 C -->|"f"| X1 C -->|"g"| X2 C -->|"<f, g>"| Prod ```
In category theory, a product comes equipped with two projection morphisms, $\pi_1$ and $\pi_2$, which extract the first and second elements from the compound type. Meijer quips that mathematicians start their projection indexing at 1 rather than 0 because they have probably never written a line of C code in their lives. Crucially, mathematicians also recognize that a type must have a way to be created: what developers call a constructor or factory function. In the diagram, given any source type $C$ with two functions $f: C \to X_1$ and $g: C \to X_2$, there is a unique mediating morphism (written as $\langle f, g \rangle$) from $C$ into $X_1 \times X_2$. Commutativity simply means that mapping an input through the constructed tuple function and then taking the first projection yields the exact same result as applying $f$ directly.
[19:35](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1175s) The Incompleteness of OOP Interfaces vs. Mathematical Rigor
Meijer engages an audience member—whom he humorously dubs "Mr. Generic" after struggling to pronounce his name—who already grasps the categorical formalism. For the rest of the audience, Meijer maps the categorical product directly to Scala's tuple implementation: the projection functions $\pi_1$ and $\pi_2$ correspond to Scala's `_1` and `_2` methods. The factory operator takes two functions $f$ and $g$ and yields a function that maps an input value $c$ to a pair `(f(c), g(c))`.
Comparing the mathematical formulation to Scala's standard library `Product2` trait, Meijer argues that the mathematics is actually far cleaner and more concise: - Scala's definition is cluttered with boilerplate: `trait Product2[+T1, +T2] extends Product`, abstract field declarations, and type variance annotations (`+T1`, `+T2`) representing covariance and contravariance, which he waves off as far too complicated for the current point. - Standard Scala lacks the categorical pair-construction combinator at the type level because implementing it directly would require functions to be treated as first-class objects within the category itself—the exact problem Martin Odersky had to navigate and the core subject of the lecture.
Beyond verbosity, Meijer emphasizes a critical difference between an object-oriented interface and a mathematical specification: “the nice thing that they do that we never do is when they Define a type they talk about properties of the type what properties should a product Define have because if you look at this definition in Scala right from here it says nowhere that when you create a topple out of two values and you project from that topple the first value that you actually get the value that you put in there right nothing says this here.”
In Scala or Java, a malicious or lazy programmer could satisfy the compiler by implementing `_1` and `_2` to always return `null`. The code compiles and adheres strictly to the interface signature. Meijer jokingly advises the developers in the room to do just that: implement traits by returning `null`, and when colleagues file bug reports, immediately reject the tickets with the retort that the specification failed to state the required behavioral properties. While they scramble to write better specs, one can take a break, grab a beer, sit in meetings, add the work to a resume, and negotiate a higher salary. In contrast, categorical diagrams enforce behavior through equational laws (such as $\pi_1 \circ \langle f, g \rangle = f$), ensuring that getters actually retrieve what was put in.
[25:03](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1503s) A Century of Delay: Stealing from Church and McCarthy
Meijer points out that these ideas are far from novel. John McCarthy defined tuples, pairs, and list-processing primitives in Lisp back in 1960. Going even further back, Alonzo Church formalized tuple encodings in the pure lambda calculus in 1928:
```mermaid flowchart LR accTitle: Timeline of Tuple Formalization accDescr: Chronological timeline highlighting Alonzo Church in 1928, John McCarthy in 1960, and Java 8 in 2015 still lacking native tuples. T1["1928: Alonzo Church (Lambda Calculus)"] T2["1960: John McCarthy (Lisp Pairs)"] T3["2015: Java 8 (Still lacks built-in tuples)"]
T1 --> T2 --> T3 ```
Meijer expresses exasperation that despite nearly a century passing between Alonzo Church's 1928 papers and Java 8's release in 2015, mainstream languages like Java still lack first-class, built-in tuple support: “Look this guy here came up with this in 1928 if you read the papers from Church he was doing this kind of toples in Java 8 it's 2015 last time I checked there are still no proper toples in the language.”
He diagnoses the root cause of this lag: mainstream developers and language designers are intimidated by mathematicians and their notation, choosing to ignore them instead of taking advantage of their findings. Showing a portrait of Church, Meijer gestures to the massive forehead and head size, remarking that Church's brain was ten times the size of an average programmer's. Software engineers should overcome their fear, exploit the massive intellectual groundwork category theorists and logicians laid decades ago, and steal their ideas directly into modern programming language design.
[26:29](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1589s) The Debate Over Lambdas and Staying Humble Before Theory
Erik Meijer points out that developers often take pride in ignoring theory. When C# introduced delegates, the attitude was that formal theory was unnecessary. When C# emerged, a dispute broke out between the C# and Java camps. The Java camp insisted they had no need for lambdas or delegates because they already had virtual methods. Meijer notes that this history teaches an enduring lesson: “Never say never.” Because James Gosling publicly declared that lambdas were unnecessary, Sun and Oracle could not easily reverse course without losing face. Meijer jokes that Gosling first had to retire, move through companies like Google, and work on self-driving cars at Stanford before Java could finally introduce lambdas and method references in Java 8.
Beyond office politics and language rivalries, Meijer cautions developers against arrogance toward theoretical computer science and mathematics. Rather than downplaying mathematics, engineers should remain open to ideas that have already been rigorously explored decades prior.
> “You should always stay humble and hungry. You always always want to learn. If these mathematicians come up with something, you know, but you better have a look at it because maybe it's something that you can use.” — Erik Meijer
[28:07](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1687s) Debunking the Myth that Objects Model the "Real World"
Meijer tackles the classic object-oriented dogma that objects exist to model real-world concepts like customers and orders. While developers are forced to write such business logic in their day jobs, the core constructs programmers actually enjoy working with are abstract data structures like lists and trees. Meijer observes that real-world trees bear no resemblance to trees in source code, and physical lists on a refrigerator never get garbage collected or completed the way lists in memory do. The belief that object-oriented programming is fundamentally about mirroring the physical world is, in his view, completely unfounded.
To reinforce this, Meijer references Eiffel creator Bertrand Meyer, noting that even an object modeling a person is merely a set of bits in memory, making it at least twice removed from reality. Because real-world modeling is an illusion, code should be treated with the same formal mathematical rigor applied to abstract mathematical objects.
Furthermore, programmers suffer when they fail to formalize types and contracts. Without precise mathematical properties, an uncooperative colleague can write a method that simply returns `null` and claim the interface contract is satisfied because the properties were never formally pinned down.
- Developers spend their day jobs on "boring" domains like customers and orders, but computer science itself centers on formal data structures. - Bertrand Meyer's philosophy underscores that in-memory data representations are inherently disconnected from physical entities. - Without property-based formal definitions on types, implementations can trivially meet type signatures (e.g., returning `null`) while violating operational intent.
[31:31](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=1891s) Reflection, Smalltalk Blocks, and Dijkstra's Zero-Based Indexing
Before category theory provided the foundation for functional interfaces, programming languages attempted to treat methods as objects via reflection. In Java, reflection lets a program inspect class types, retrieve methods, and invoke them dynamically. Meijer remarks that reflection is intellectually fascinating—writing software that can reason about its own behavior is something even human beings struggle to do when acting foolishly after a night out. However, reflection is ultimately an awkward "cop-out" because reflective method representations operate in an artificial meta-level rather than as ordinary, first-class language objects.
This desire to treat methods as values was solved decades earlier. Dave Thomas and the Smalltalk community had already embraced "blocks," which reified methods as first-class objects despite Smalltalk’s heavy emphasis on real-world anthropomorphic messaging. Meijer jokes that he cannot talk too much about Smalltalk because its arrays start at index one, which is unacceptable to any Dutch computer scientist. He cites Edsger W. Dijkstra's argument for zero-based indexing, illustrating how Dijkstra counted his handwritten manuscripts by starting with the state of having zero pages before adding the first.
```mermaid flowchart TD accTitle: Approaches to Reifying Methods as First-Class Objects accDescr: Diagram contrasting reflection as a meta-level cop-out against first-class reifications like Smalltalk blocks and Java 8 lambdas.
subgraph MetaApproach["Meta-Level Approach"] Reflect["Reflection / Class Inspection"] Reflect -->|"indirect invocation"| MetaInvoke["Method.invoke(...)"] end
subgraph DirectApproach["First-Class Value Approach"] Smalltalk["Smalltalk Blocks"] JavaLambda["Java 8 Lambdas / Method References"] MathExp["Category Theory: Exponentials (Z^Y)"] end
Reflect -.->|"criticized as cop-out"| DirectApproach ```
[34:43](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2083s) Exponentials and Function Counting: Math vs. Java
Turning back to category theory, Meijer explains how category theorists formalize methods as objects using the concept of **exponentials**. When examining academic slides packed with Greek symbols and diagrams, one encounters the notation $Z^Y$ (or $Z$ to the power of $Y$) to denote a function from $Y$ to $Z$. The notation stems from basic combinatorics: given finite sets, the number of distinct mathematical functions from a domain $Y$ to a codomain $Z$ is precisely $|Z|^{|Y|}$.
To make this intuitive, Meijer walks through basic set sizes: - A function from `Unit` (a single-value type, size 1) to `Boolean` (size 2) yields $2^1 = 2$ possible functions: one returning `true`, and one returning `false`. - A function from `Boolean` (size 2) to `Unit` (size 1) yields $1^2 = 1$ possible function: mapping both inputs to `unit`.
Meijer points out that this clean counting argument breaks down completely in languages like Java. A Java method with the signature `Boolean -> void` does not have just one implementation; it can perform arbitrary console logging via `println`, execute network I/O over HTTP, or trigger reflection. In impure imperative languages, hidden contexts and side effects violate the clean semantics of mathematical functions. Meijer spots a smiling Haskell programmer in the audience and contrasts Java's leaky abstraction with pure functional languages where functions truly mirror mathematical mappings.
[39:37](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2377s) Mr. Haskell and Escaping the Rabbit Hole
Erik Meijer opens with a humorous jab at the functional programming purist, dubbed “Mr. H” (Mr. Haskell), whose code ends up being roughly ten times longer than typical Java code by the time he finishes wiring together all his monads. Having such a colleague can be advantageous, Meijer jokes, because you can learn from him, write practical code implicitly, and move on with your career while he is trapped overcomplicating things:
> “And by the time he has figured out how to compose all these monads you’re already here at Foo Café listening to your next talk that you can put on your resume and you get ahead isn’t that great?”
Turning back to category theory, Meijer strips away the dense mathematical symbols and translates the concepts into plain programming terminology. Assume a programming language $L$ that supports tuples, with types $A$ and $B$. A function $A \to B$ can then be characterized via a factory method derived from a functor. However, explaining this introduces the concept of a functor itself. Meijer warns that checking Wikipedia for a definition usually plunges developers straight down another intimidating rabbit hole of Greek letters and abstract definitions.
[41:56](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2516s) Functors, Java Generics, and the Laws of Mapping
Decoding the formal mathematics into standard programming language concepts, a functor in a typed language is simply a generic type constructor. In Java, generics were introduced back in Java 5 (which Meijer quips has already been a long time, despite Java generics having irritating limitations, such as only permitting reference types and not primitive types like `int`). A functor associates every type $A$ with a new type $C\langle A\rangle$. For example, `List<T>` is a functor because it can be instantiated with another type, such as `Integer`.
```mermaid flowchart LR accTitle: Functor Mapping Flow accDescr: Diagram showing how a functor maps a function between types A and B to a function between C of A and C of B. subgraph BaseTypes["Underlying Types"] A["Type A (e.g., Integer)"] -->|"f (e.g., toString)"| B["Type B (e.g., String)"] end subgraph FunctorTypes["Functor Types C<T>"] CA["C<A> (e.g., List<Integer>)"] -->|"map(f)"| CB["C<B> (e.g., List<String>)"] end ```
Crucially, a functor must provide a `map` operation. If a function exists from $A \to B$ (such as `toString` converting an integer to a string), `map` lifts that function so it can transform $C\langle A\rangle$ into $C\langle B\rangle$ (converting a `List<Integer>` into a `List<String>`). Beyond just having a `map` method, category theory demands that it obey two strict algebraic laws: 1. **Identity preservation:** Mapping the identity function over a container (doing nothing to each element) must return the original container unchanged. 2. **Composition preservation:** Applying `map(f)` followed by `map(g)` must yield the exact same result as mapping the combined function `map(g. f)`.
Meijer highlights that category theorists are secretly efficiency freaks: this composition law is an optimization trick that fuses pipeline stages, avoiding the creation of wasteful intermediate data structures (such as creating an intermediate list of strings just to measure their lengths).
- While category theorists view `map` as an essential law that must accompany generic types, conventional object-oriented languages neglected this for decades; Java only finally introduced a standard `map` method on `Stream` in Java 8. - From a foundational category theory perspective, a functor maps between two distinct categories (which can be thought of as two distinct programming languages, like adapting between 0-indexed Java arrays and 1-indexed Smalltalk arrays). - An **endofunctor** is simply a functor that maps a category back to itself (staying entirely within a single programming language).
[47:34](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2854s) Functions as First-Class Objects and Currying
Meijer notes that he had to cheat slightly when defining `map`: the operation inherently requires being able to pass a function as an argument. Prior to Java 8, Java lacked first-class lambdas, making it impossible to define `map` cleanly.
Looking at the formal Cartesian closed category diagrams from mathematicians like Joachim Lambek, one sees an evaluation morphism `eval` and an exponential object representing function spaces. Functional programmers immediately recognize this categorical apparatus:
> “And of course Church or this is Haskell B. Curry will say, ‘Oh, but this is currying in Haskell!’”
While Haskell developers were accustomed to currying and higher-order functions since the late 1980s, the mainstream object-oriented world lagged behind, with many enterprises still running ancient Java versions like Java 6.
[49:41](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=2981s) Why Instance Methods Do Not Exist
Meijer returns to his earlier simplification of treating all methods strictly as static morphisms, citing Bjarne Stroustrup to justify doing away with instance methods entirely. As early as 1979, Stroustrup pointed out that an instance method is merely a static function that takes the `this` pointer as an explicit extra argument tupled with the method's other parameters. Today, even C++ includes lambdas, demonstrating that virtually every mainstream modern programming language has finally adopted first-class functions after decades of resisting mathematical foundations.
To prove this is not just a C++ design quirk, Meijer turns to the official Java Virtual Machine Specification:
> “So if you want to have an even more boring document than the Java Language Specification, you should read the Java Virtual Machine Specification.”
In the JVM specification, when executing any instance method or class method, local variable 0 is always reserved for the reference to the instance (`this`), while user-passed parameters populate subsequent local variables starting at index 1. At the execution level, Java also has no real instance methods—only static procedures whose initial parameter is `this`.
Meijer concludes by acknowledging the elephant in the room that object-oriented programmers often raise: inheritance. While dogmatists preach "favor composition over inheritance" (to which Meijer jokingly advises making those colleagues look bad and getting them fired), inheritance is fundamentally a dirty, pragmatic implementation trick designed for code reuse via virtual tables (v-tables). Formalizing the semantics of inheritance mathematically is notoriously difficult, having formed the basis of entire doctoral dissertations, such as the seminal work by William Cook.
[53:35](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3215s) Decoding the Greek: Method References as Exponential Objects
Erik Meijer moves past inheritance to continue "decoding the Greek" mathematical formalism of category theory into something programmers can actually grasp. Rather than dwelling on impenetrable notations involving exponential superscripts and abstract lambda binders—which he jokes would put everyone straight to sleep after eating hot dogs and hamburgers—he translates the concept directly into modern object-oriented programming. In Java terms, a function type paired with an `apply` method is defined relative to an arbitrary type `A` and a method `m` that takes an argument of type `B` and yields a return type `C`. Under the hood, defining a method on `A` really means `m` has `A` as its first implicit parameter and `B` as its second.
```mermaid flowchart LR accTitle: Method Reference as Exponential Object accDescr: Diagram illustrating how an instance method corresponds to an exponential object factory returning an apply method. subgraph OO["Object-Oriented View"] direction TB M["Method on A:<br/>a.m(b): C"] end subgraph CT["Exponential Object Translation"] direction TB FR["Factory Method:<br/>a::m returns Function<B, C>"] APP["apply(b)"] FR --> APP end M <-->|"Isomorphic"| FR APP -->|"Evaluates to"| RES["Same as a.m(b)"] ```
From this perspective, a factory method written with the double-colon syntax (`::m`) accepts an instance of `A` and produces a function object of type `Function<B, C>`. That resulting function object exposes an `apply` method such that invoking `apply(b)` produces the exact same result as calling `a.m(b)` directly. Meijer polls the audience to see who uses IntelliJ IDEA and notices how aggressively the IDE prompts developers to refactor lambdas into method references. When an attendee named Paul confirms he frequently accepts this refactoring suggestion, Meijer jokes that Paul can now march into work and demand a substantial raise:
> “So now you can go to your boss and say in Foo Café I learned that I'm freaking using exponential objects from category theory in my coding; I need a raise because that son of a next to me has no clue what they're doing—they're still using whatever virtual methods, but I know exponential objects.”
The deeper revelation for Meijer is that Java's designers ended up building exact categorical structures without realizing it. He asserts that Java language architects likely had zero formal category theory in mind when designing Java 8, yet arrived at the exact same mathematical formulation:
> “I'm 100% sure that the Java language designers had no idea of category theory, but yet they came up with exactly the same solution; that is the amazing thing.”
Because two completely independent groups—pure theorists decades earlier and pragmatic language designers solving developer ergonomics—converged on the identical construct, it signals the existence of an underlying universal truth in computer science.
- Java method reference syntax (`::m`) acts as the constructor/factory for the categorical exponential object. - Calling `(a::m).apply(b)` is strictly equivalent to calling `a.m(b)`. - The convergence of category theory and Java 8 method references reflects foundational mathematical laws emerging naturally in software engineering.
---
[58:37](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3517s) Hom-sets, Adjunctions, and the Inevitability of Monads
Meijer addresses the elephant in the room: he hasn't yet uttered the notorious "M-word"—monads. Returning to the underlying category theory, he explains the machinery connecting exponential objects to adjunctions and hom-sets. He jokes that a "hom-set" sounds like fish eggs (clarifying in Dutch that "kuit" or "hom" refers to fish roe/caviar), but in reality, $\operatorname{Hom}(A, B)$ simply denotes the set of all morphisms from object $A$ to object $B$.
In categorical terminology, the relationship governing exponential objects states that a morphism from a product $X \times Y \to Z$ is naturally isomorphic to a morphism $X \to Z^Y$. In programming, this is nothing more than currying and uncurrying: transforming a function taking two arguments into a higher-order function taking one argument that returns another function. The method reference conversion is precisely this isomorphism, transforming a lambda expression `b -> a.m(b)` into the curried method reference `a::m`.
Meijer shows executable Scala code to prove this is not merely abstract theory, illustrating how exponential objects form a pair of adjoint functors. Crucially, any pair of adjoint functors canonically gives rise to a monad. Because Java 8 adopted exponential objects via lambdas and method references, it implicitly adopted adjunctions, making full-blown monads structurally inevitable in future versions of the language:
> “Java will have monads because monads are related to adjunctions, and adjunctions come from exponentials.”
He notes that the classic State monad arises directly from this exact product-exponential adjunction, though he defers that full demonstration to a future talk.
- $\operatorname{Hom}(A, B)$ is just mathematical vocabulary for the collection of all functions/morphisms between types $A$ and $B$. - Currying and uncurrying represent the natural isomorphism between $\operatorname{Hom}(X \times Y, Z)$ and $\operatorname{Hom}(X, Z^Y)$. - Every categorical adjunction generates a monad; specifically, the product-exponential adjunction generates the State monad. - Meijer predicts that within 10 to 20 years, mainstream languages like Java will fully embrace explicit monads as a consequence of adopting exponentials.
---
[01:02:22](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3742s) Commemorating the Theory: Tattoos and Closing Remarks
Wrapping up the evening at Foo Café, Meijer quips that after consuming plenty of beer during the meetup, attendees are properly primed to head out and get permanent ink. He displays two sample tattoo designs on his slides: one rendering the rigorous category theory commutative diagram and its direct correspondence to Java constructs, and a second, lighter alternative for those who find the first option too intimidating.
With a laugh, he tells the audience that he negotiated an exclusive arrangement with a local tattoo shop:
> “I made a special deal with Liz's tattoo parlor where if you show your Foo Café t-shirt, you will get a discount on any of those two tattoos.”
The presentation ends on this humorous high note, met with enthusiastic applause from the audience.
## Notable quotes > [58:37](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=3517s) Java will have monads because monads are related to adjunctions, and adjunctions come from exponentials. — Erik Meijer
> [08:14](https://www.youtube.com/watch?v=JMP6gI5mLHc&t=494s) Curry-Howard isomorphism says that a type is a theorem and the program is the proof for that theorem. — Erik Meijer
## Mentioned Erik Meijer, Joachim Lambek, Leslie Lamport, Alonzo Church, John McCarthy, James Gosling, Bertrand Meyer, Dave Thomas, Edsger W. Dijkstra, Martin Odersky, Haskell B. Curry, Bjarne Stroustrup, William Cook, Foo Café, Java, Java 8, Scala, Smalltalk, Haskell, C#, C++, Lisp, IntelliJ IDEA, Android, JVM Specification, Java Language Specification
## Video description Category Theory is the Mathematicians' interpretation of interface-based design, so whenever you hack together a new API in your favourite OO language, it is always a smart idea to ask the question x -LT "What would x do?" applied to the Category Theorist that worked on your same problem already decades ago. Since lambda expressions are the new hot topic all across programming language land these days, we will invoke our question of conscience with "Joachim Lambek" and learn that Java 8 lambdas and method references are simply a Cartesian Closed Category, proving yet again that interfaces are the OO developers' interpretation of Category Theory.
Foo Café is an independent and physical meeting place for people of all backgrounds and expertise within the IT-industry in the Malmö/Lund region. Foo Café is aimed at those interested in sharing, learning and creating. Join the fun at foocafe.org
[Source](https://www.youtube.com/watch?v=JMP6gI5mLHc)