What is the difference between chain()
(from ramda
package) and map()
in Javascript?
In both functions the programmer inputs an object and some lambda/function and gets a certain calculation of it. Thanks.
chain
and map
each operate on an abstract type. map
operates on any Functor. This is any item with a map
function that obeys certain laws. chain
operates on a Chain element. Similarly, this is something with a lawful chain
function, as well as having lawful apply
and map
functions.
Ramda provides map
and chain
functions that will work with types fulfilling these contracts. It also supplies implementation for certain built-in types (functions, arrays, and objects for map
and functions and arrays for chain
.)
To see how they differ, it's simple enough to compare their signatures:
// map :: Functor f => (a → b) → f a → f b
// chain :: Chain m => (a → m b) → m a → m b
You can think about it like this: the function supplied to map
takes an item of type A and returns one of type B. map
accepts that function and a container holding type A and returns a container holding type B. The function supplied to chain
by contrast takes an item of type A and returns a container holding type B. chain
accepts that function and a container holding type A, returning a container holding type B.
You can think about it as though chain
unwraps one level of containers compared to map
.
For example, let's say we had a function factors
, which returns the factors of an integer (factors(14) //=> [1, 2, 7, 14]
, for instance.) Here is how map
and chain
would work on a list of numbers:
map(factors, [12, 15]) //=> [[1, 2, 3, 4, 6, 12], [1, 3, 5, 15]]
chain(factors, [12, 15]) //=> [1, 2, 3, 4, 6, 12, 1, 3, 5, 15]
Or if we had a Maybe
type used to simplify null-handling with the subtypes Just
to signify a value and Nothing
to signify some null in the computation. We might write a safe square root function such as
const sqrt = (n) => n > 0 ? Just(Math.sqrt(n)) : Nothing()
Then we see these differences between map
and chain
.
map(sqrt, Just(25)) //=> Just(Just(5))
chain(sqrt, Just(25)) //=> Just(5)
map(sqrt, Just(-25)) //=> Just(Nothing)
chain(sqrt, Just(-25)) //=> Nothing
And finally, for functions, for reasons described in another SO answer,
map(f, g) //~> x => f(g(x));
chain(f, g) //~> x => f(g(x))(x);
You can see from their signatures, that there is some relationship between map
and chain
, but they are distinct functions, used for very different purposes. chain
is related to what is sometimes called flatMap
, as it flattens out (one level) of the sort of result created by map
.
But the best way to think about them is to look at the signatures and the laws tied to these functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With