Sun, Mar 14, 2021 9-minute read

Contemplating on bothering to develop my Haskell skills or not [0], I decided to write this post instead.

Monads. It's a terrible name. Why do programmers tends towards "if-else" and other seemingly "simpler" programmatic abstractions than they do to Haskell abstractions e.g., "monads". It's because "monad" is a terrible name. We do not call "if-else" statements "conditional bifurcations" (or even attempt to be clever and shorten that to "conbifs"). We call them "if-else statements". It sounds almost like English class from the 2nd grade or ESL 101. It's comfortable.

But another reason that I do not personally tends towards Haskell is because I do not like the obsession with composition [3]. Category-theoretic obsessionism with regards to functional programming is, for all practical purposes, an intellectual fetish. It's math porn for software nerds, through and through. I have tried it and it can be fun but it feels like a mathematical instagram feed quickly scrolling past any detail of minutiae and creating the most abstracted and generalized instant-gratification-framework that you can possibly dream up.

But, I enjoy absurd reductions for intellectual discussion, so let's attempt to go down a slightly adjacent reductionist path. Let's pull away even further from a "category". Let's discuss why composition is not the final answer to life, the Universe and everything else.

There is a much richer kind of abstraction that encompasses composition and many things else. That is the notion of relationships. Yes, relationships exactly like the one you have with your family and friends. Relationships exactly like the ones you have with certain foods you like or dislike. Relationships like the ones between the columns of your favorite SQL table at work or the relationships between that table and other SQL tables. Relationships like the one between the composed object, let's call it C, and the objects being composed, which we will call A and B.

Yes, A and B are composed into C. That is their relationship. Except, its not. It's one possible "implementation" of a relationship.

If I were to ask you: 'what's the relationship between A and C'? How would you answer? Well, there is only one possible way. We must determine: How are A and C different? (If you ask "how are A and C similar?" then that is actually a weakened form of the first question).

Oh, well that is easy! They are different by B! Just compose A and B and you get C, duh. This is true. But, A and C are only different by B if we compose them under the specific composition operation that composing them under produces C. If we had chosen any other composition operator then A and B might have not composed into C. They might have not composed at all. In fact, who is to say that only B when composed with A using the exact same composition operator gets you to C? What if we use the same composition operator and exchange B with D? What if A and D compose into C as well under the same composition operator?

As we can see, looking at composition tells us in almost no way how to define the fundamental difference, and thus the relationship between A and C. We have no answer to our question. If I ask "what is the relationship between A and C?" then I only get one possible answer from any choice of category and composition (which usually ends up being something like "this bundle of arrows" is your answer). In fact, given any mathematical, logical, or social framework I can only get one of the many possible answers to that question. This captures the idea that relationships depend almost entirely on the context of the discussion.

So, is there a fundamental answer to how A and C are different/related? It feels rather unintuitive to assume not. In our physical Universe, there always seems to be a satisfying answer to this question. We can understand differences, and thus relationships, via time and space. We can understand relationships via differentials in measurements and observations. But physicality is merely one closed context.

And the brain does not limit itself to the single context of physicality. We can abstract. But even in any abstract discussion, around physicality or not, we can reduce (and thus, here comes the aforepromised reductionism) everything to only one of two possibilities:

  1. objects of our discussion
  2. and relationships between those objects

Test it out for yourself. You will find that any discussion on any topic is nothing more than some set of objects and the relationships between those objects. This is very much a reason for why all of category theory end up being entirely represented by dots and arrows, and then also why nearly any mathematical or software idea can be given a category-theoretic interpretation. It's not the categories. It's the objects and relationships. But, when we only discuss objects and relationships we are not restricted to the axioms of categories. It's a higher abstraction. Meaning, that there is likely an infinite other theories with clear differentiators from category theory that can be used to discuss objects and relationships. Some of them will entirely not involve composition.

There is one further reduction we can make: relationships are objects. Thus, the entirety of our abstractions becomes effectively singular: objects. "Objects" is the only necessary abstraction for anything programmatic or mathematical [1].

But if everything is just an object then why talk distinctly about relationships (over other kinds of objects) in our abstract discussions? Because relationships are the most important kinds of objects.

Here is the catch-22 for why relationships really are the most important objects. What is an object? It can be defined as something which can be differentiated in some way from anything else except itself (given a context). So, if two objects cannot be differentiated from one another then are they really two distinct objects? Relationships help us "know" what all the possible objects of discussion really are. For example, if I gave you two definitions of objects then how could you possibly know if they are two definitions of the same object or two distinct objects? You could only know if you work through relating the two definitions yourself, or being supplied a relationship definition. Relationships act as objects whose existence defines distinction for other objects [5]. This implies further things such as: a single object in one discussion may be many objects in another discussion (and vice versa) dependent on which relationships exist (or don't exist) in the discussions.

But this all does relate back to composition and Monads. Differentiating objects within a discussion/context/program is one of the most powerful ways to define or instantiate "relationship" objects. And one of the ways to do that is via composition. By supplying the collection of possible objects (even if not explicitly listed e.g., the category of all sets) and a defined composition operator on that collection of objects we set ourselves up to begin defining relationships between objects (e.g., inclusion of sets). And one of the ways to define a composition operator is via a bind method on a Monad. And conditional bifurcations, er ... I mean "if-else statements", are a composition operation as well [2]. Designing these composition contexts help us define differentiation, which means we really are attempting to define all possible relationships, and thereby determining all possible objects (as being differentiable from already determined objects) programmatically. Because, constructing objects is all that we really care about at the end of the day. And we do this by creating a restriction from the higher abstraction of "objects and relationship" to the framework of "categories and composition". But, it's not really categories or composition that we are chasing (or should be chasing). We are always in pursuit of defining objects (which is often some final "program"), and we construct them best via relationships.

Some other things besides composition in the world of programming are about defining relationships as well, such as inheritance and polymorphism (but they focus on similarities instead of differences). Differentiable programming is another example (and actually focuses on differences, and the differences of differences!).

So, the obsession with composition is in fact an obsession with relationships, which is an obsession with objects. And there you have it, you now have endured an Object-Reductio-Totally-Absurdum exercise [4] and I still have yet to decide how much I want to care about Haskell.

Final question: Are there other abstractions outside of composition to effectively define/construct differences -> relationships -> objects?


  1. I did read about Haskell's software transactional memory in it's primary concurrency management library and I thought that sounded pretty good. But, STM and Monads, etc. can all be implemented in any turing-complete programming language even if the performance or syntax are not ideal.
  2. Aha, then object-oriented programming had it right! Nope, they got it right in name only. Not conceptually. Sorry, Javascript and Python. However, Type Theory comes a little closer to "getting it right". I am not sure that there is a "right" or that if there is if any of us know or ever will know what that "right" is.
  3. They determine how two procedures/"functions"/programs will compose.
  4. I do realize that the historical reason for the obsession with composition predates Haskell and functional programming within the field of pure mathematics by decades.
  5. This absurd reductionism or any other should almost never be dwelt on and entirely forgotten after it's revelation.
  6. There is also the never ending discussion on what an object's relationship is to itself, as there is truly only one possible relationship and that relationship is exactly what equality is supposed to be even though we never use "equality" properly anywhere within mathematics (or programs). You may have noticed this rabbit hole yourself when trying to define a single "equality" function or method for any objects in your code. There is only one true equality check - every single little thing must be the same about the two objects being compared - otherwise it is actually a relationship function or method. And a lot of relationship checks - not equality checks - determine conditionals such as belonging to some collection or not. Anyways, that is a rabbit hole post in of itself exploring how fundamental relationships actually are in programming.