
Composability: From Callbacks to Categories in ES6 - alrex021
https://medium.com/@homam/composability-from-callbacks-to-categories-in-es6-f3d91e62451e
======
lmeyerov
Interesting: as far as I can, this is promises, except there is a final
strictness point at the end of the composition. That is, in turn, analogous to
a one-shot form of old FRP formulations, where there is a final
strictness/execute call. We already see that in JS libraries, like 'subscribe'
in Rx: [https://github.com/Reactive-
Extensions/RxJS/blob/master/doc/...](https://github.com/Reactive-
Extensions/RxJS/blob/master/doc/api/core/operators/subscribe.md)

FWIW, I'm actually not that thrilled about this sort of deferred approach. In
Rx, that is part of the reason 'hot' vs 'cold' documentation has to exist, and
I've seen many people struggle with it in theory & practice.

~~~
inglor
This comment is correct - promises in JavaScript started like this and settled
on their current API for ergonomics. Here is a standard promise implementation
with deferred execution that never took off: [https://github.com/then/lazy-
promise](https://github.com/then/lazy-promise)

A lot of tough calls had to be made and pragmatic best interest of users
typically triumphed over purity.

A promise is monadic if you drop exceptions and use the `then` overload which
is `bind`. You have a `pure` - `resolve`.

The promise constructor has to exist to interop with callbacks but for no
other reason really.

~~~
gavinpc
Come to think of it, the "strictness" of the Promise constructor is more
ergonomical for concrete, day-to-day usage, where you're binding specific
things together.

It became a pain point for me when using Promises as part of a larger
abstraction, where the exact use was not known. Then I've worked around the
strictness by embedding a "trigger" into a set of Promises so that I can set
them off all at once, after they are all created.

Good article, btw. One of these days the Monad/Category lightbulb is going to
go off for me, and this brought me closer to that using a familiar example.

------
girvo
As you start to look at these concepts, and Ramda, I highly recommend playing
with ramda-fantasy[0] and the fantasy-land[1] spec that it implements. Super
useful, and really made this sort of functional programming "click" for me
(and, has really cleaned up some abstractions in a couple production projects,
too!)

[0] [https://github.com/ramda/ramda-fantasy](https://github.com/ramda/ramda-
fantasy)

[1] [https://github.com/fantasyland/fantasy-
land](https://github.com/fantasyland/fantasy-land)

~~~
spraak
Here[0] is a Node REPL with rambda and rambda-fantasy functions as globals. It
feels so fun to use, like a whole other language.

E.g. `map(x => x*2, [1, 2, 3])` (no need to write `R.map`)

[0] [https://github.com/hemanth/ramda-repl](https://github.com/hemanth/ramda-
repl)

------
nailer
Note his call back hell is exacerbated by the unnecessary 'else' after
checking for errors and returning.

I'm not sure that .bindTo() chaining reads any better than .then() chaining or
async.waterfall().

~~~
JasonSage
The point isn't really to argue for another naming scheme for Promises. The
construction of the Callback class is used to build up the reader's
understanding the Monadic structure before introducing Categories and Kleisli
Categories. The comparison of the structure of these abstractions comes up
several times.

I think the final example (of myLongOperation) reads extremely well, and is
pretty minimal, as the author states.

------
shakiba
Looks like a new hell!

~~~
kccqzy
How is this a new hell? This is some elegant, mathematics-derived abstraction.

~~~
scribu
It will turn into a hell because JavaScript lacks Haskell's strong type
system. The tooling will not give you early warning if you pass a plain
function into a construct that expects a promise etc.

~~~
homami
That's very true. But on the other hand dynamic typing is what enables us to
play with JavaScript and re-create many concepts from FP in plain JS. This is
not easy in many strongly typed languages which their type system falls short
of Haskell's (that supports ADTs, kinds, recursive types, etc.).

~~~
scribu
Yes, dynamic typing allows experimentation. But just because you can make JS
look like Haskell doesn't mean it's the most effective way to get stuff done.
You'd be better off writing Haskell and transpiling it, IMO.

Note that I'm talking about writing an entire application in this style, not
just sprinkling categories here and there.

------
joostdevries
I was recently thinking while working with ES6 Promises that I liked to have
something equivalent to Haskells `do` notation. Or Scalas `for` comprehension.

Does something like that exist?

If not maybe I should try Kleislis instead. But I'd like my code to be
accessible for my colleagues. And it's my rule of thumb that I try not to use
point free constructions (like Kleislis) because a lot of colleagues will no
longer understand my code easily.

~~~
joostdevries
On second thought: I guess Async Await are like a `do` notation specifically
for Promises...

~~~
homami
That's true. await sequence actions much like do notation.

~~~
joostdevries
..and it's flat instead of nesting.

------
jacinabox
The article didn't really sell that arrows have an advantage over monads as
far as callbacks are concerned.

~~~
homami
Do you have any particular use-case in mind for arrows in JS?

------
spraak
Really fun read!

------
dozzie
Arent you guys around JavaScript tired of changing your programming paradigm
every half a year?

~~~
BinaryIdiot
Why would anyone made such a change every year? Many people write articles
about better ways to do X in many languages but that doesn't mean you change
everything to follow that today. Maybe it informs your decisions tomorrow,
maybe it doesn't. Ultimately you don't need to do anything here.

Personally I don't use promises and won't use this either but that's only
because I am working on a code base that needs to work in more places (so no
ES6 for me and no I don't need the extra complexity in my build and debugging
steps to do a transpile).

~~~
homami
I'd love to know which runtimes do you have to support which don't support ES6
if you don't mind? I imagine you're dealing with old browsers.

~~~
BinaryIdiot
At my previous job it was older browsers but my primary avoidance of ES6 is
related to my open source project (msngr.js) where I want to ensure I support
not only older browsers but also node.js 0.10. I could use ES6 and transpile
with babel but I try not to do that when possible to keep the build process as
simple as possible.

If there was a specific ES6 feature that I think would hugely benefit my
productivity or if I was working on a project that could utilize ES6 in other
ways I would certainly use it more.

