javascriptfunctional-programmingramda.jssanctuary

Merge multiple objects with Sanctuary.js


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)([]).


Solution

  • 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.