I am trying to merge multiple objects with Sanctuary.
With Ramda.js I would do something like this (see the REPL here):
const R = require('ramda');
const initialEntry = { a: 0, b: 1 };
const entries = [{c: 2}, {d: 3, e: 4}, {f: 5, g: 6, h: 7}];
R.reduce(Object.assign, initialEntry, entries);
However, with Santuary.js the following line of code throws an exception.
S.reduce(Object.assign)(initialEntry)(entries)
Here is the exception I am getting:
! Invalid value
reduce :: Foldable f => (a -> b -> a) -> a -> f b -> a
^^^^^^
1
1) {"a": 0, "b": 1} :: Object, StrMap Number, StrMap FiniteNumber, StrMap Integer, StrMap NonNegativeInteger, StrMap ValidNumber
The value at position 1 is not a member of ‘b -> a’.
I am puzzled by this error message. Am I using S.reduce
incorrectly? Also, I get no errors if I write S.reduce(Object.assign)(initialEntry)([])
.
This is because the first argument to reduce
takes a function with the signature a -> b -> a
. Unlike Ramda, Sanctuary is strict about such signatures. You have to supply it a function that takes an argument of one type and returns a function that takes an argument of a second type and returns an argument of the first type. Object assign
does not do that. It takes a variable number of objects in one go.
You can fix this by replacing Object.assign
with a => b => Object.assign(a, b)
:
const initialEntry = { a: 0, b: 1 };
const entries = [{c: 2}, {d: 3, e: 4}, {f: 5, g: 6, h: 7}];
const res = S.reduce(a => b => Object.assign(a, b)) (initialEntry) (entries);
console.log(res);
<script src="https://bundle.run/sanctuary@1.0.0"></script>
<script>const S = sanctuary</script>
The Ramda version works because it expects a binary function to reduce
. While Object.assign
is technically variadic, everything works fine if you treat it like a binary function.