收集参数以应用于Java/Scala中的curried函数

收集参数以应用于Java/Scala中的curried函数,java,scala,generics,java-8,currying,Java,Scala,Generics,Java 8,Currying,我想在Java8中创建一个类,它能够递归地创建一个对象,该对象具有一个基于我添加的参数获取函数参数的方法 例如,我希望能够做到这一点: new X().param(23).param("some String").param(someObject) .apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c)) 然后,apply方法将收集的参数应用于给定函数 我觉得在维护类型安全性时,这应该是不需要考虑的,但我不太清

我想在Java8中创建一个类,它能够递归地创建一个对象,该对象具有一个基于我添加的参数获取函数参数的方法

例如,我希望能够做到这一点:

new X().param(23).param("some String").param(someObject)
  .apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c))
然后,apply方法将收集的参数应用于给定函数

我觉得在维护类型安全性时,这应该是不需要考虑的,但我不太清楚如何实现。如果我可以将Scala中的解决方案转换为Java8,那么它也是受欢迎的。如果不可能,我也会接受解释原因的答案

到目前为止,我基本上是这样的:

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
            );
    }
}
class参数{
最后一个参数;
公共参数cmd(一个参数){
this.param=param;
}
公共参数cmd param(B){
返回新的ParamCmd(b);
}
公开无效申请(职能f){
//这部分我不清楚
}
公共静态void main(字符串[]args){
新的ParamCmd(0.param(“oops”).param(新对象())
//构造的函数参数与声明相反
.apply((对象c)->(字符串b)->(整数a)->
参数为“+a+”+b+”+c
);
}
}

正如代码注释中所指出的,我的问题是按照调用param()的顺序保留函数参数,并实际应用参数。

这并不能回答您的问题。然而,它可能会帮助人们找到解决方案,或者解释为什么在Java和/或Scala中不可能实现

可以在C++中完成,参数任意数量,不丢失类型安全性。呼叫端如下所示。不幸的是,C++中的lambda语法相当冗长。

bar{}.param(23).param("some String").param(4.2).apply(
    [](int i) {
        return [=](std::string s) {
            return [=](double d) {
                std::cout << i << ' ' << s << ' ' << d << '\n';
            };
        };
    });

很抱歉,我只能提供一些Scala方面的线索:

也许看一看会有帮助$

很像函数。未结婚的

param(23).param("some String").param(someObject)
如果您不关心类型安全,可以使用累加器列表来实现。如果你想保留这些类型,你可以使用HList的Shapeless,它有一个方便的tupled方法

param()的实现:

范例

scala> val m = new Method().param(1).param("test")
m: Method = Method@1130ad00

scala> m.l
res8: shapeless.HList = test :: 1 :: HNil

对于数量不限的参数,我能想到的唯一解决方案是在Scala中使用异构列表

这在Java中可能不可行,因为依赖路径的类型正在进行类型级计算

使用异构列表和路径相关类型:

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
}

第二种更为有限的方法是为每个函数长度创建多个类,该方法可能适用于Java,它返回下一个大小的函数长度类,将值包装到某个最大长度-请参阅Scalaz中的ApplicationBuilder:

您似乎需要Applicationve.HList是我的第一个想法,但是shapeless不容易翻译成Java:)如果可能的话,我确实想保留这些类型,但我可能会接受一个黑客攻击。期待您的解决方案。这一切看起来都很有趣。很酷,如果我决定在Scala中实现类似的东西,我可能会这样做:)
import shapeless._
import HList._
import syntax.std.traversable._

class Method(val l : HList = HNil) {
  def param(p: Any) = new Method( p :: l )
}
scala> val m = new Method().param(1).param("test")
m: Method = Method@1130ad00

scala> m.l
res8: shapeless.HList = test :: 1 :: HNil
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
}
23Hello
65Hello