2014-02-17 5 views
9

In Scala sagen wir, ich habe eine Funktion wie folgt aus:typisierte Funktion und Currying in Scala

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

so kann ich tun:

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

Gibt es eine Möglichkeit, dies zu ändern Funktion currying zu verwenden ohne den Typ des zweiten Arguments "zu verlieren"?

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 

Antwort

6

Eine Variante von Senias Antwort, um strukturelle Typisierung zu vermeiden:

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

Sie sollten Senias Antwort wirklich akzeptieren, alles, was ich tat, war eine kleine Variante zu zeigen! Abgesehen von Kudos gibt es keinen materiellen Vorteil, wenn man einen Ruf über 20k hat. –

13

Funktionen nicht Typparameter haben können, müssen Sie eine benutzerdefinierte Klasse wie folgt verwenden:

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

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

strukturelle Typisierung vermeiden Sie benutzerdefinierte Klasse explizit erstellen könnte:

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

Ich denke, der zweite Vorschlag ist besser, da es doesn‘ t verwenden Strukturtypen (die immer mit Reflexion afaik?). Zumindest bekomme ich die folgende Feature-Warnung: Warnung: "reflective access von Strukturtyp member method apply sollte aktiviert werden , indem der implizite Wert scala.language.reflectiveCalls sichtbar gemacht wird. Dies kann durch Hinzufügen der Import-Klausel 'Import Scala erreicht werden. language.reflectiveCalls 'oder indem Sie die Compiler-Option -language: reflectiveCalls setzen. " – reikje

2

Nicht wirklich eine Lösung für Ihr Problem, sondern nur darauf hinweisen, dass Sie immer noch die zweite Version Ihrer Funktion verwenden können, wenn Sie den Typen explizit angeben:

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