We will get started by taking a look at one of the most used operations in these abstractions: map.
We've been using map for a long time, in order to transform sequences. Thus, instead of creating a new function name for each new abstraction, library designers simply abstract the map operation over its own container type.
Imagine the mess that we would end up in if we had functions such as transform-observable, transform-channel, combine-futures, and so on.
Thankfully, this is not the case. The semantics of map are well understood, to the point that even if a developer hasn't used a specific library before, he will almost always assume that map will apply a function to the value(s) contained within whatever abstraction the library provides.
Let's look at three examples that we have encountered in this book. We will create a new Leiningen project...