2014-02-17 73 views
9

柯里在Scala中,让我们说我有这样的功能:类型化功能和斯卡拉

def foo[R](x: String, y:() => R): R 

所以我可以做:

val some: Int = foo("bar", {() => 13 }) 

有没有办法来改变这种使用功能柯里没有“失去”第二个参数的类型?

def foo[R](x: String)(y:() => R): R 
val bar = foo("bar") <-- this is now of type (() => Nothing) 
val some: Int = bar(() => 13) <-- doesn't work 

回答

6

senia回答中的一个变体,以避免结构分型:

case class foo(x: String) extends AnyVal { 
    def apply[R](y:() => R): R = y() 
} 

val bar = foo("bar") 
val some: Int = bar(() => 13) 
// Int = 13 
+0

你应该真的接受senia的答案,我所做的只是展示一个小变体!除了荣誉之外,声望超过20k没有任何实质性的好处。 –

13

功能无法具有类型的参数,你必须使用一个自定义类这样的:

def foo(x: String) = new { 
    def apply[R](y:() => R): R = y() 
} 

val bar = foo("bar") 
val some: Int = bar(() => 13) 
// Int = 13 

为了避免结构性打字,你可以创建自定义的明确类:

def foo(x: String) = new MyClass... 
+0

我认为第二个建议是,因为它不”好t使用结构类型(它总是带有反射afaik?)。至少我得到以下功能警告:警告:“应用结构类型成员方法apply的反射访问应启用 通过使隐式值scala.language.reflectiveCalls可见 这可以通过添加import子句的导入scala来实现。 language.reflectiveCalls'或通过设置编译器选项-language:reflectiveCalls。“ – reikje

2

不是一个真正的解决问题的方法,但只是想指出,如果你提供明确的类型,你仍然可以使用你的函数的第二个版本:

scala> def foo[R](x: String)(y:() => R): R = y() 
foo: [R](x: String)(y:() => R)R 

scala> val bar = foo[Int]("bar") _ 
bar: (() => Int) => Int = <function1> 

scala> bar(() => 12) 
res1: Int = 12