Lets “solve” programming (once again, LOL), in a couple of pages, simply because why tf not. and to put the LLMs and their shills and worshipers into shame (yes, yes, I know, they do not have any).

We will build a simple abstract and general “meta-theory”, which is, like a religion grounded on Buddha’s compassion, provide a foundation of peaceful and cooperating traditions, which guide people in their decision making in a overwhelmingly complex Reality by providing easy to understand and easy to apply “heuristics” or “rules of thumb”.

This “meta-theory”, however, is also explanatory and allows to make “testable” informed decisions, just as any truly scientific theory.

Let’s start from the most wonderful almost metaphysical level of the “underlying structure of the Universe”, and via the recently discovered the Curry-Howard Correspondence and very related Algebraic Data Types go all the down to the boring low-level implementation details (high-level, interface-level programming is sometimes still fun).

When Simon back in the sixties examined the “Architecture of Complexity”, he noticed that a particular recurrent “pattern” – a Layered Hierarchical Structure emerge again and again at all level (of abstraction).

This is still true, of course. It implies that the only way to program systems that mimics and represents some aspects of the Real World, is to discover and identify this inherent layered structure in the “domain” and make an one-to-one correspondence between each layer of domain to a layer of corresponding functional DSL in a program, and each distinct concept of the “domain” (at its proper level in an overall hierarchy) to a distinct type which captures and represents named concept at an appropriate level of abstraction, within is own orthogonal, self-contained, lose-coupled module.

Michael Jackson and Barbara Liskov have taught these universal principles in the 70s (seventies, mfrs!). Simon wrote his paper in the late 60s.

Let’s observe some more “fine” structure in the overwhelming complexity around us.

Mountain rivers and trees form what we would call Directed Graphs. What we call “derivatives” and “the chain rule” is how much each stream contributes to the overall momentum of a river, with respect of how much water it contributes and how steep it is when it joins the river.

Yes, I am tracing back the most fundamental abstract mathematical concepts all the way back to the aspects of Reality, from which they have been generalized and abstracted out. You, probably, should have such habit too.

A mountain river is a canonical example of an emergent process caused by nothing but the Causality principle. Every process in the whole Universe is exactly like this, but the river abstraction is much more easy to comprehend.

A tree is another such process. Trees emerge due to “localized” sub-processes, which “know nothing” about existence of anything beyond their immediate locality. All cell biology, at the levels of tissues, “works” in this way.

There are 3 common structural patterns in these process, which can be structurally abstracted as:

  • a “step” (an arrow between 2 “points”)
  • a “join” (of two “arrows”)
  • a “fork” (of two “arrows”)

Notice that all these structures are “directed”. It is said that a “fork” and a “join” are isomorphic to each other, and, it appears that this is the case, except that the “direction of the arrows”, which is a definitive part of these very structures, has been neglected. So, no, not isomorphic.

It is also said that they are dual to each other – all we can do is to “reverse the direction of the arrows”. While this is a perfectly valid abstract mathematical operation, which yield a perfectly “valid” transformed abstraction, in Reality (or in this particular Universe) such “transformations” are literally impossible. The direction of the “arrows” cannot be thrown out of the window.

Everything else can be build out of these three building blocks. Yes, in Reality forks, joins and steps are not necessarily “binary”, not necessarily perfectly symmetric, but that is all to it.

Now what exactly these abstract structural patterns capture? Well, “steps” and “joins” capture the Causality Itself. “Forks” capture what we call Potentiality – possible outcomes (of processes) or possible “choices” (distinct paths, based on outcomes).

Notice that “forks” and “joins” are from principally very different, non-overlapping “domains”, which is exactly why “isomorphism” and “duality” is just a nice abstract bullshit.

This, and only this, is exactly why there are only 3 Algebraic Data Types – Products, Sums and Mappings. These types are in one-to-one correspondence with the universal building blocks of Reality. This correspondence, of course, has been discovered, not invented.

There is another correspondence – the distinct patterns in the Algorithm Charting Techniques of the 70s, which, unsurprisingly are “forks”, “joins”, “steps” and recursion, which must always be though off as a spiral, not a “loop”.

Lets add to this the Lambda Calculus, with its notions of a binding, environment, abstraction and application, which, not accidentally, are in an one-to-one correspondence with the “introduction” and “elimination” rules of Natural Deduction (bindings also have “introduction” and “elimination”).

Now we have all the necessary and sufficient building blocks to build or “construct” everything commutable (constructible).

The only missing block is “lexical” closures. Closures “naturally arise” when we study the bindings within nested frames of environment in the context of actually implementing the Simply Typed Lambda Calculus.

At the intuitive level, closures just properly capture “mental concepts” by avoiding any human language-related ambiguity, by “capturing the meaning of each word/term” . A word could have more than one associated meaning (being overloaded), so we have to know (capture) exactly which meaning was used in the definition of a mental concept (which is also a “capture” of some pattern itself).

There are also “The Universal Machine” – the Meta-Circular Evaluator of Abelson and Sussman (the Wizards), and the System F Omega as the intermediate language of GHC. These two show that, indeed, this is all we need.

At the level of programs there is also lots of structure. The most fundamental aspect is non-leaking Abstract Data Types, the notion popularized by Barbara Liskov (again). Proper ADTs are self-contained and orthogonal to one another, so they allow independent understanding (as sort of semantic closure) and thus independent development (by “other people”), which, in turn, allow different even swapable implementations. The most important underlying principle however, is that it facilitates thinking at an appropriate level of abstraction – at the level of “public” interfaces. It is also implicitly tends to keep abstractions within the bounds of abstraction barriers and to keep abstraction at the same higher-level, without capturing unnecessary and irrelevant implementation details, as in bad C++, where literally everything is an implementation detail.

And this is basically it. This is all you need to program correctly. Specification, Abstraction Algebraic Types,and Modularity, which implies ADTs and modules with narrow, stateless mostly-functional interfaces.

Yes, there are also DDD, TTD and some meaningful parts of Agile. But these all are consequences of the universal principles outlined above.

DDD is just a methodology of identifying, capturing and establishing that one-to-one correspondence betwen the inherent hierarchical layered structure of [complexity] of the “domain” and the corresponding hierarchical layered structure of lauers of ADTs and layers of DSLs . It does so by capturing the meaning from the “concepts of the mind” (of an “expert”), which are mental closures, into the Algebraic Types and their representations, which are sort of “semantic closures”. The “one-to-one” is the crucial part, otherwise nothing will work as expected.

TDD is even simpler. There is a wonderful, almost mystical aspect of Algebraic Data Types, which binds and holds everything together. Just as a mountain river or a tree can be build one stream and one branch at a time, any Algebraic Type can be build one data-constructor, one slot or one clause at a time, without breaking anything which is already “Out There”. One can add a new “item” to any Algebraic Type and then proceed to test (first!), and implement it without taking anything else into consideration (less mental strain). This is the essence and the how of the Bottom-Up processes, popularized in Graham’s “On Lisp”. It is not a random coincidence that types are so finely composable, it has something to do with Monoids and nature of addition operation as “putting together”, weighted sums and the Causality Principle itself.

And Agile is just a spiral-shaped, recursive (which they call “iterative”) fixed-point shaped process. It is literally a narrowing spiral which eventually converges on a good-enough “epsilon” . Each “iteration” has to be “complete” (the Always Be Compiled, “never leave the code in an inconsistent state”, and “yay! all tests passed”). Notice how “one clause at a time” is what makes this actually possible. Everything else is just a fancy bullshit.

So, next time you want to program just re-read and apply this. Make a petty mathematical theory, defining the entities (using sets) their attributes, and relations among entities (using mappings). Programming is understanding (and necessarily theory-building) after all. You have to make Algebraic Data Types with are in an one-to-one correspondence with the problem domain, to choice the “shape of the data” – the data structures that mimic the inherent structure within the domain, and then, according to the “Data Dominates” maxim, the code “will almost write itself”. Familiar well-understood math will be the “candle” that illuminates evrything.