收集参数以应用于Java/Scala中的curried函数
我想在Java8中创建一个类,它能够递归地创建一个对象,该对象具有一个基于我添加的参数获取函数参数的方法 例如,我希望能够做到这一点:收集参数以应用于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方法将收集的参数应用于给定函数 我觉得在维护类型安全性时,这应该是不需要考虑的,但我不太清
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