Collect arguments to apply to curried functions in Java/Scala

currying, generics, java, java-8, scala

Solution

For an unlimited amount of parameters, the only solution I could think of is with Heterogeneous Lists in Scala.

It is probably isn't feasible in Java as there is type level computation going on with path-dependant types.

Using Heterogeneous Lists and Path-Dependant types:

import scala.language.higherKinds

object Main extends App {
  val builder1 = HCons(23, HCons("Hello", HNil))
  val builder2 = HCons(42L, builder1)

  val res1:String = builder1.apply(i => s => i + s)
  val res2:String = builder2.apply(l => i => s => (i+l) + s)
  println(res1) // 23Hello
  println(res2) // 65Hello
}

sealed trait HList {
  type F[Res]
  def apply[Res]: F[Res] => Res
}
case class HCons[Head, HTail <: HList](head: Head, tail: HTail) extends HList {
  type F[Res] = Head => (tail.type)#F[Res]
  def apply[Res]: F[Res] => Res = f => tail.apply(f(head))
}
case object HNil extends HList {
  type F[Res] = Res
  def apply[Res]: F[Res] => Res = identity
}

This code prints:

23Hello
65Hello

The second, more limited way of doing this, but which might work with Java, is to create multiple classes for each function length, which returns the next sized function length class wrapping the value, up to some maximal length - See the Applicative Builder in Scalaz: "Scalaz Applicative Builder"

Problem

I would like to create a class in Java 8 which is able to recursively create an object which has a method that takes a function parameter based on the parameters I added. For example, I would like to be able to do this: ``` new X().param(23).param("some String").param(someObject) .apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c)) ``` The apply method would then apply the collected parameters to the given function. I feel this should be possible without reflection while maintaing type-safety, but I can't quite figure out how. A solution in Scala is also welcome, if I can translate it to Java 8. If it's not possible, I'll also accept an answer that explains why. What I have so far is essentially this: ``` class ParamCmd<A,X> { final A param; public ParamCmd(A param) { this.param = param; } public<B> ParamCmd<B, Function<A,X>> param(B b) { return new ParamCmd<>(b); } public void apply(Function<A,X> f) { // this part is unclear to me } public static void main(String[] args) { new ParamCmd<Integer,String>(0).param("oops").param(new Object()) // the constructed function parameters are reversed relative to declaration .apply((Object c) -> (String b) -> (Integer a) -> "args were " + a + " " + b + " " + c ); } } ``` As noted in the code comments, my problems are keeping the function parameters in the order of the calls of param(), and actually applying the parameters.

Original source