Compose n functions where the innermost function expects multiple arguments
First, there's something weird happening here


const f = uncurry(compn2([sqr, inc, sub]));
console.log(f(5, 2)); // yields 16



I would assume that this composition is doing this

sqr (inc (sub (5) (2)))
// sqr (inc (2 - 5))
// sqr (inc (-3))
// sqr (-2)
// =&gt; 4


But upon closer inspect, it's because your uncurry function is unconventionally flipping the arguments


const uncurry = f =&gt; (y, x) =&gt; f(x) (y);



Nevermind that tho, we don't have to agree on it. I'll show you a way to solve your problem without even depending on it.



I'm going to introduce a function papply which procedurally applies a curried function



const papply = f =&gt; ([x,...xs]) =&gt;
  x === undefined ? f : papply (f(x)) (xs)

console.log(papply (x =&gt; y =&gt; y - x) ([2,5])) // 3
// (x =&gt; y =&gt; y - x) (2) (5)
// (y =&gt; y - 2) (5)
// 5 - 2
// =&gt; 3






I'm also going to introduce a dramatically simplified compn – there's nothing wrong with yours, but it will help reduce some of the complexity of the example I provide.



const compn = ([f,...fs]) =&gt; x =&gt;
  f === undefined ? x : f(compn (fs) (x))

const inc = x =&gt; x + 1

const f = compn ([inc, inc, inc])

console.log(f(3))
// compn ([inc, inc, inc]) (3)
// inc (compn ([inc,inc]) (3))
// inc (inc (compn ([inc]) (3)))
// inc (inc (inc (compn ([]) (3))))
// inc (inc (inc (3)))
// inc (inc (4))
// inc (5)
// =&gt; 6






OK, let's get to it then !



const sqr = x =&gt; x * x

const inc = x =&gt; x + 1

const sub = y =&gt; x =&gt; x - y

const compn = ([f,...fs]) =&gt; x =&gt;
  f === undefined ? x : f(compn (fs) (x))

const papply = f =&gt; ([x,...xs]) =&gt;
  x === undefined ? f : papply (f(x)) (xs) 

const f = compn([sqr, inc, papply(sub)])

console.log(f([2, 5]));
// sqr (inc (papply (sub) ([2,5]))
// sqr (inc (papply (sub (2)) ([5])))
// sqr (inc (papply (x =&gt; x - 2) ([5])))
// sqr (inc (papply (5 - 2) ([])))
// sqr (inc (papply (3) ([])))
// sqr (inc (3))
// sqr (4)
// =&gt; 16






Of course it requires that the function is applied a bit differently ...

// this
f([2,5])

// instead of
f(5,2)


I don't think that change will bother you much tho, especially considering every other function of yours (including compn) is manually curried. This stays true to calling all functions with one arg. If multiple values are required, a tuple is provided – or in this case, an Array, as Tuple is absent in JS.

It's an interesting question and I think you had an interesting approach. The complexity ultimately steered me to thinking about a different solution. Just my 2 cents, hope it helped some ^_^