Orders as Categories — Why Comparison Matters More Than Sorting
When we compare things in programming, we instinctively think about sorting:
numbers, timestamps, scores…
But comparison is a much broader idea than sorting.
Sometimes we don’t need to arrange values from smallest to largest. Sometimes we only need to know whether one thing can stand in place of another.
Category theory captures this using the idea of order — and surprisingly, once you look closely, orders already behave like categories.
Starting With a Simple Relation
Take a set of elements and a relation ≤ between them.
We don’t assume numbers. We don’t assume sorting. We only assume the relation behaves consistently.
To be consistent, the relation must obey a few rules.
Rule 1 — Reflexive
Every element relates to itself.
a ≤ aThis just means comparison must never fail on identical values.
If a type cannot be used where the same type is expected, the system is already broken.
Rule 2 — Transitive
If a relates to b, and b relates to c, then a relates to c.
a ≤ b and b ≤ c ⇒ a ≤ cThis is what makes reasoning scalable.
Without it, every check would have to be repeated manually — nothing could safely compose.
When a relation satisfies just these two rules, we call it a preorder.
From Preorder to Partial Order
a ≤ b
b ≤ aeven when a and b are different.
To remove this ambiguity, we add one more rule:
If two elements relate both ways, they must actually be the same element.
This is called antisymmetry.
Now the relation becomes a partial order.
At this point the structure becomes stable enough to represent dependencies — no circular chains remain.
From Partial Order to Total Order
We strengthen the relation one more time.
For every pair of elements, one must relate to the other:
a ≤ b or b ≤ aNow every pair can be compared.
This gives a total order — the kind required for sorting.
Sorting algorithms rely entirely on this property. Without it, they cannot consistently place elements.
Why This Forms a Category
Think of a ≤ b as meaning you can go from a to b.
Now three natural things happen:
Those are exactly the rules a category needs. So we didn’t invent a category here — we simply noticed that a normal ordering relation already behaves like one.
What Is a Hom-Set (Without the Scary Name)
Forget the word hom-set for a moment. Imagine you ask a very practical question:
“In how many ways can I go from A to B?”
That’s it. All the possible paths from A to B — we collect them in one place. Category theory just gives that collection a name:
Hom(A, B)You can read it as: “all valid arrows from A to B”
In a Normal Programming Situation
Between two types there can be many functions:
String → IntYou might have:
So:
Hom(String, Int) = { parseNumber, length, hashCode, digitCount, ... }Many arrows live inside the hom-set.
But In an Order Category
Now remember — our arrows don’t represent functions anymore.
They represent a statement:
a ≤ bSo we don’t ask:
“Which function converts a to b?”
We ask:
“Is a allowed where b is expected?”
Only two outcomes exist:
So the hom-set shrinks dramatically:
Hom(a, b) = { one arrow } if a ≤ b
Hom(a, b) = empty if notThe set no longer stores implementations. It stores permission.
Why This Is Called a Thin Category
Because every hom-set has at most one element.
No alternatives. No competing arrows. No different implementations.
Just true or false.
That’s what “thin” means:
there isn’t room for multiple arrows anymore
Conclusion — More Than Sorting
We began with a simple comparison: can this replace that?
From that, we discovered structure:
And surprisingly, this already satisfies the laws of a category.
But this category is different.
Its arrows don’t describe computation — they describe permission. Its hom-sets don’t hold functions — they hold truth.
So ordering isn’t just about arranging values. It’s a way to reason about what programs are allowed to exist.
