2014-02-17 2 views
9

В Scala скажем, у меня есть функция, как это:типизированных Функции и Карринг в 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

Вариант ответа сени, чтобы избежать структурной типизации:

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, все, что я сделал, это показать небольшой вариант! Помимо Kudos, нет никакой существенной выгоды в репутации более чем 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?). По крайней мере, я получаю следующее предупреждение о функции: предупреждение: «Отражательный доступ к методу элементарного типа структуры должен быть включен , делая неявное значение scala.language.reflectiveCalls видимым. Этого можно достичь, добавив условие импорта« import scala ». language.reflectiveCalls 'или путем установки опции компилятора -язык: 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 
Смежные вопросы