2014-02-17 113 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