Hacker News new | past | comments | ask | show | jobs | submit login

So this is a bit ranty and I hope it doesn't come off as too rude, but here goes:

Let's talk about functions. Why is id . f = f . id = f? id . f is a function which takes some argument, pushes it on the stack, calls f, pushes the result from f on the stack and calls id. This is two function calls and you go two stack levels deep. Just f is one function call and one stack level deep. If f and id are real functions executing on real hardware, then id . f is not strictly equal to f due to unavoidable side effects even if id and f are both pure functions, e.g. you may have not enough stack space to execute id . f, but you could execute just f. Real functions executing on real hardware aren't exactly the same like the pure mathematical notion of a function. If Haskell is a language for writing computer programs executing on actual computers, then id . f ≠ f; and if it isn't, then it's not very useful.

Abstractions are well and good, but I must be able to reason how the machine will work while executing my program. Take the official Python implementation - CPython for example. It's nowhere near as fast as C if you write your code naively, but there is very little surprising about it. Or take C. If you write e.g.

    int id(int x) { return x; }
    int f(int x) { return 2*x; }
    int id_f(int x) { return id(f(x)); }
Then the compiler is free to compile id to a noop and id_f to be exactly the same as f, but it is not required. Most people won't write a program which requires that behaviour by the compiler in order to work correctly.

If the Haskell compiler is required to perform such optimisations, then I would concede id . f = f; just like tail recursion optimisation is required in Scheme, so tail recursion is actually equivalent to loops, rather than being just mathematically equivalent.

The broader point I want to make is that a computer programming language is inescapably tied to the reality of how hardware executes instructions and one must have some guarantees on how what is written will translate to machine execution.

Another thing is that once you reach a certain level of abstraction, you lose your ability to reason about the concrete things in that class. I'll illustrate what I mean.

Let's construct the set of Handleds. A handled is a thing that has a handle, and a handle is a cylindrical protrusion affixed to the object, that can be grasped by an average adult human hand and pushed or pulled along an axis perpendicular to the cylinder's height. So, a TNT detonation device is a handled, since you have a handle on the plunger you press to detonate the TNT. A door also has a handle. Your laptop bag has a handle. A table leg also technically counts as a handle and you can use it to move the table. The thing is, while you would have a theory on how to make handles, such that they would be easily operated by people, the fact that an object has a handle tells you nothing of the object, other than it can be manipulated with a hand.

Pretty much the same goes for a category. Yes, you can compose two elements of the category into a third. So... what does it do? You don't know. The problem is, the two lumps of fat that sit in your skull need to affix some concrete properties on the object in order to think about it. Functions are series of instructions that transform values. Or maybe they're relations, if you're a mathematician. But the essence of a function isn't in its composability (at least for programmers), it's in its usage as a unit of execution. Maybe also in its usage as a way to organise your source code.

There's no point in explaining something as "it's a category" any more than in a car salesman starting out by pointing all the handles on the car and how the bumpers can be grabbed as ersatz handles in case you need to get a handle on the situation. Saying something is a category is a deferred meaning that you can only understand once you know what that something is, so it's more of a mental burden than an explanation of anything.

Category properties may be simple, but their relation to the actual execution of a program is anything but. If you want to explain Haskell, maybe start off with the simple parts. Like how what you write executes on the actual machine and work your way up.




Your point about equating f . id = id is related to what the equality sign means.

Presumably you don't object to the notion that sin(a + b) = sin(a) cos(b) + cos(a) sin(b), even though the left and right hand sides are totally different in terms of computation.

That's because you know that such identities, while indeed abstracting over computational details, have real meaning and are extremely useful in mathematical thought (and algorithm design; you can use that equation to implement an efficient numeric oscillator).

Given that you probably accept that trigonometric equality, you can't really dismiss equational reasoning in software as useless just because it abstracts over stack frames and machine instructions. That kind of abstraction is exactly the point.


I gave an example above of categories being useful for a very mundane purpose: https://news.ycombinator.com/item?id=10529150

Most categories that arise in practice aren't “just” categories - they have interesting extra structure. For instance, platonic Hask, the category of Haskell types and total functions, is bi-Cartesian-closed. The categories that arise when modeling databases are typically not closed (from a programmer's POV, this means that functions aren't first-class objects - you can't store them in tables), but they have finite coproducts (UNION ALL) and products (SELECT ... FROM multiple, tables). SQL-style aggregate functions are nothing but commutative monoid objects in these categories. etc.


Correct, and when the article says "any composition operator that observes these laws will be ... free from edge cases" this is not strictly true. Nonetheless, any such object will be freer from edge cases, and the concept is still extremely useful.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: