
Common combinators in JavaScript - jxub
https://gist.github.com/Avaq/1f0636ec5c8d6aed2e45
======
skrebbel
This site embodies everything I dislike about functional programming: an
attitude that shorter and less specific is better.

What use is a line like

    
    
        const S = f => g => x => f(x)(g(x));
    

for _anyone_ except someone who _already groks_ what the S combinator does and
is for?

Why do these combinators have single-letter names anyway? Does that help
anyone? Even Haskell, heaven on earth for single-letter guess-what-i-mean
coders, has actual names for half of these - how is knowing that "flip" is
also "the C combinator" helpful in _any_ way?

Now, I'm not trying to diss this page in particular, and I very much am not
trying to diss functional programming. I like functional programming. But I
think that when hype shifted from OOP to FP, we threw half the baby out with
the bathwater (ok, maybe a quarter baby). Naming is important and FP does not
have any feature in particular that makes "I" a better name than "identity".

I think programming in general, and FP in particular, will become a better
place if we all grow up a bit and stop pretending we're too smart to need good
naming.

~~~
joeframbach
const S = f => g => x => f(x)(g(x));

I'm more likely to write

    
    
        const geed = g(x);
        const effed = f(x);
        const S = effed(geed);
    

I have no idea when I would actually write a structure like this though. Can
someone please fill those names in with something like `buildComparator` or
`Math.max.apply` or something, anything, that remotely makes sense?

~~~
dmitriid
It's one of those things that you arrive at yourself. You rarely, if ever,
understand them from Haskell-ish mathematical-ish constructs like these.

Sometimes you could end up with this code in situations like this:

    
    
       const data = getDataForUser(user);
       const transformer = getTransformersForGDPR();
       const sanitizedData = transformer(data);
    

where getTransformersForGDPR returns a single function that may contain a
chain of data transformations.

The example is contrived, of course, but you do end up with similar constructs
especially if you have been exposed to functional programming.

~~~
joeframbach
Ah, that does make sense. I think this happens in the React world sometimes,
where a single state holds the source of truth for everything, and we end up
passing parts of it around to other methods to make decisions.

    
    
       const data = getDataFromState(state);
       const transformer = getTransformersForState(state);
       const sanitizedData = transformer(data);

------
tobr
Is there a reason why functional programming algebra insists on using one
letter identifiers?

~~~
T-R
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.

~~~
FnuGk
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 ?

~~~
T-R
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.

------
kbutler
Note that this page should be considered a "cheat sheet", rather than an
explanation. For explanations, see the reference section lower in the page.

------
agumonkey
I like this new ascii table

