我正在尝试将多个对象与Sanctuary合并。
使用Ramda.js,我会做类似的事情(请参阅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);
但是,对于Santuary.js,以下代码行将引发异常。
S.reduce(Object.assign)(initialEntry)(entries)
这是我得到的例外:
! 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’.
我对这个错误消息感到困惑。我使用S.reduce
的方式有误吗?另外,如果我写S.reduce(Object.assign)(initialEntry)([])
也不会出错。
答案 0 :(得分:3)
这是因为reduce
的第一个参数采用签名为a -> b -> a
的函数。与Ramda不同,Sanctuary对此类签名非常严格。您必须为其提供一个函数,该函数接受一种类型的参数,然后返回一个函数,该函数接受第二种类型的参数,并返回第一种类型的参数。 Object assign
不会这样做。一口气拿出可变数量的对象。
您可以通过将Object.assign
替换为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>
Ramda版本之所以起作用,是因为它期望二进制函数为reduce
。尽管Object.assign
在技术上是可变参数,但是如果您将其视为二进制函数,则一切正常。
答案 1 :(得分:1)
S.concat
可以专用于StrMap a -> StrMap a -> StrMap a
。结果,S.reduce (S.concat) ({})
的类型为Foldable f => f (StrMap a) -> StrMap a
。这可以专门用于Array (StrMap a) -> StrMap a
。例如:
> 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}
保护区不提供用于合并任意对象的功能。