From the documentation:
var duplicate = n => [n, n];
R.chain(duplicate, [1, 2, 3]); //=> [1, 1, 2, 2, 3, 3]
R.chain(R.append, R.head)([1, 2, 3]); //=&g
It is probably easier to first look at the abstract version of the R.chain for functions and to distinguish between functions m: r -> a treated as monads and functions f: a -> r -> b treated as Kleisli arrows, as mentioned in this answer.
Then R.chain is defined as:
// (a -> r -> b, r -> a) -> r -> b
R.chain = (f, m) => x => f(m(x))(x)
This can be useful, when x is some kind of configuration parameter, the same for both f and m. Then a = m(x) is the value returned by m for that parameter, and g = f(_)(x) is the function returned by f for the same parameter. Think of x as some kind of environment that goes into both m and f. Then the above definition can be broken down as:
R.chain = (f, m) => x => {
const a = m(x)
, g = a => f(a)(x)
return g(a)
}
In comparison, the R.map for functions corresponds to the case when f is independent of that parameter x:
// (a -> b, r -> a) -> r -> b
R.map = (f, m) => x => f(m(x))
which, of course, is the usual function composition from the outside.
Another conceptual approach to define chain (aka bind in Haskell) is to apply map (aka fmap) followed by flatten (aka join).
R.chain = (f, m) => {
// m1: r -> r -> b
const m1 = R.map(f, m)
// flattening to fm1: r -> b
const fm1 = x => m1(x)(x)
return fm1
}
Now for m = x => R.head(x) and f = a => x => R.append(a)(x), R.chain(f, m) is equivalent to putting the parameter x into both f and m and composing the results:
x => R.append(R.head(x))(x)
which gives the expected result.
Warning. Note that the R.append function here must be curried as it represents the Kleisli arrow a -> r -> b. Incidentally, Ramda provides the same named function also as uncurried, but it is the curried one used here. To see this, let us get our custom uncurried R.append:
const appendCustom = (a, b) => R.append(a, b)
Then note how Ramda's REPL throws an error and gives unexpected result:
// Define our own uncurried append const appendCustom = (a, b) => R.append(a, b) R.chain(appendCustom, R.head)([1, 2]); // => t(...) is not a function
http://ramdajs.com/repl/?v=0.25.0#?%2F%2F%20Define%20our%20own%20uncurried%20append%0Aconst%20appendCustom%20%3D%20%28a%2C%20b%29%20%3D%3E%20R.append%28a%2C%20b%29%0AR.chain%28appendCustom%2C%20R.head%29%28%5B1%2C%202%5D%29%3B%0A
What really happens here, appendCustom is executed in its curried form: appendCustom(a)(b), with the second call is delegated to some internal function returning the error.