back

by tobr·8y ago·view on hn ↗
Is there a reason why functional programming algebra insists on using one letter identifiers?
6 comments
It's intentionally to get across the idea that you don't, and shouldn't, know anything about these arguments within this scope beyond "this is a function" and "this is an argument". These functions just define how to combine things; if you knew any more about the arguments, it would be breaking the abstraction.

The only better names you could really give are ones like func1, func2, arg1, arg2, which don't add any information, just add noise. Trying to get any more specific than that would leave the reader trying to interpret the meaning of the name, but the whole point is that it's strictly "apply this thing to that in this way, without looking at what they are". Even fix-point, which is unarguably cryptic, really needs a paragraph explanation for the unfamiliar more than it would benefit from better names.

That makes sense for the arguments to the outermost function but not to the function it self. Why call it A instead of apply and the then have a big cheat sheet where you put that A means apply and T means applyTo ?
I think those single-letter names like "S combinator" are a holdover from Math notation, where it was a practical consideration, but in practice in functional programming, those names aren't used (I certainly haven't memorized them); If you look at the Haskell column on the page, you can see that they're actually named for readability (though it might not initially seem like it if you don't do a lot of coding in Haskell):

- K is "const" and C is "flip"; they're generally used to for arguments to a higher order function: "map (const 5) myList", "foldl (flip f) 0 myList"

- Psi is "on", since it's regularly used to construct a new function "h = f `on` g"

- S is a specific type of application, called infix as "f `ap` x", but also has an operator to intentionally make it look more like just line noise: "f < * > x". (Had to add spaces to this operator so HN wouldn't interpret it as italics)

The operators might seem opaque, but the idea is to make it more visually apparent that it's a pattern, not some application-specific business logic. There are lots of concepts of "apply" - there's pure application ($), Applicative application (< * >), Monadic application (=<<), etc. - writing them out would distracting to read. Using operators makes it easier to skim and get the general idea of how the code works without worrying about the underlying structural details, while still being precise about them.

Mathematicians insist on one-grapheme identifiers, partly due to tradition and aesthetics, and partly because at some point juxtaposition came to represent multiplication, so what xy means would be ambiguous.
It is for purely pragmatic reasons. Try actually writing calculational proofs using long identifiers. You will soon find yourself wanting to be drowned in lava.

Of course, a true programmer delegates even the simplest calculation to a computer, so they have less of a need for notation that is easy to manipulate.

I refer you to my answer to a related question.

https://news.ycombinator.com/item?id=16420361

Because it truly doesn't matter what 'x' is. It could be a number, string, an Array, Map, React Component, a very specific VerifiedUserWithBillingAddress object from your domain that you're working in right now.

So then what name do you want to give 'x' in `I = x => x`? Is `something` better, more readable?

If you write these functions ad-hoc in your modules as local helper functions, then by all means, use a more appropriate name:

    [1,2,3,undefined,6].map(anIntegerOrUndefined => anIntegerOrUndefined)
But the functions presented here are not those that you should have to write yourself. They are available in the Haskell base library, in JS you can import ramda or other packages. The important thing is to know how and when to use them.
The S K I combinators were developed as the equivalent of assembly language for functional programs.

In reality, expanding a lambda expression into SKI combinators takes up a lot of space. Since the notation is mainly for language implementors, using the short mnemonics allows you to compress the size of the resultant expression.

It's the same reason why the x86 opcode is named 'mov' not 'move'.

It would definitely be harder to play combinatris with longer identifiers...

http://dirk.rave.org/combinatris/