Reputation: 1629
If f :: a -> b -> c is curried then uncurry(f) can be defined as:
uncurry :: (a -> b -> c) -> ((a, b) -> c)
I'm trying to implement the above function in javascript. Is my below implementation correct and generic enough or are there are any better solution?
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
Upvotes: 7
Views: 1435
Reputation:
Your uncurry
has three issues:
Here is a more functional approach:
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
ignores unnecessary arguments like any other function in Javascript. It reuses uncurry
, reduce
and id
.
If too few arguments are passed it throws an error, since it isn't clear in each case, which value should be returned (NaN
, undefined
).
Upvotes: 3
Reputation: 2404
It is not bad, but you assume that f
is function until you loop through all arguments.
Also if you are using es6 consider using rest operator instead of arguments
. And for ... of
is nicer syntax in es6 to loop through values of array.
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
Upvotes: 2