如果f :: a - > b - > c是curry然后uncurry(f)可以定义为:
uncurry ::(a - > b - > c) - > ((a,b) - > c)
我正在尝试在javascript中实现上述功能。我的下面的实现是否正确和通用,还是有更好的解决方案?
const uncurry = f => {
if (typeof f != "function" || f.length == 0)
return f;
return function()
{
for (let i = 0; i < arguments.length; i++){
f = f(arguments[i]);
}
return f;
};
}
const curry = f => a => b => f(a, b);
const curriedSum = curry((num1, num2) => num1 + num2);
console.log(curriedSum(2)(3)); //5
console.log(uncurry(curriedSum)(2, 3)); //5
答案 0 :(得分:2)
您的uncurry
有三个问题:
这是一种更实用的方法:
const id = x => x;
const uncurry = f => (x, y) => f(x)(y);
const uncurryn = n => f => (...xs) => {
const next = acc => xs => xs.reduce(uncurry(id), acc);
if (n > xs.length) throw new RangeError("too few arguments");
return next(f) (xs.slice(0, n));
}
const sum = x => y => z => x + y + z;
try {uncurryn(3)(sum)(1, 2)} catch(e) {console.log(e.message)}
console.log(uncurryn(3)(sum)(1, 2, 3));
console.log(uncurryn(3)(sum)(1, 2, 3, 4));
&#13;
uncurryn
忽略不必要的参数,就像Javascript中的任何其他函数一样。它重复使用uncurry
,reduce
和id
。
如果传递的参数太少,则会抛出错误,因为在每种情况下都不清楚,应该返回哪个值(NaN
,undefined
)。
答案 1 :(得分:1)
这不错,但你假设f
是循环遍历所有参数的函数。
此外,如果您使用的是es6,请考虑使用rest运算符而不是arguments
。并且for ... of
是es6中用于循环遍历数组值的更好语法。
const uncurry = f => {
if (typeof f !== "function" || f.length == 0)
return f;
return (...args) => {
for (let arg of args) {
if (typeof f !== "function") {
return f;
}
f = f(arg);
}
return f;
};
}
const curry = f => a => b => f(a, b);
const curriedSum = curry((num1, num2) => num1 + num2);
console.log(curriedSum(2)(3)); //5
console.log(uncurry(curriedSum)(2, 3)); //5
&#13;