Reputation: 5061
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)([])
.
Upvotes: 1
Views: 393
Reputation: 24856
S.concat
can be specialized to StrMap a -> StrMap a -> StrMap a
. As a result, the type of S.reduce (S.concat) ({})
is Foldable f => f (StrMap a) -> StrMap a
. This can be specialized to Array (StrMap a) -> StrMap a
. For example:
> S.reduce (S.concat) ({}) ([{a: 0, b: 1}, {c: 2}, {d: 3, e: 4}, {f: 5, g: 6, h: 7}])
{a: 0, b: 1, c: 2, d: 3, e: 4, f: 5, g: 6, h: 7}
Sanctuary does not provide a function for merging arbitrary objects.
Upvotes: 1
Reputation: 50807
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/[email protected]"></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.
Upvotes: 4