Uncurry javascript 中 n 个参数的柯里化函数

Uncurry a curried function of n parameters in javascript

如果 f :: a -> b -> c 是柯里化的,那么 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

这还不错,但是您假设 f 是函数,直到您遍历所有参数。

此外,如果您使用的是 es6,请考虑使用剩余运算符而不是 argumentsfor ... 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

您的 uncurry 存在三个问题:

  1. 如果不是所有预期的参数都传递给它 returns 柯里化函数(这不是正常的非柯里化函数的行为)
  2. 无法处理不必要的参数
  3. 实施不是很实用,因为您不重用任何东西

这是一个更实用的方法:

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));

uncurryn 像 Javascript 中的任何其他函数一样忽略不必要的参数。它重复使用 uncurryreduceid.

如果传递的参数太少,则会引发错误,因为在每种情况下都不清楚应该返回哪个值(NaNundefined)。