Функциональные литералы Scala с имплицитами - PullRequest
23 голосов
/ 13 июня 2011

Простите, если об этом уже спрашивали в другом месте.У меня есть вопрос о синтаксисе Scala, включающий значения функций и неявные параметры.

Мне удобно использовать имплициты с функцией карри в Scala.Например, если у меня была функция суммы и я хотел сделать второй аргумент неявным:

scala> def sum(a: Int)(implicit b: Int) = a + b
sum: (a: Int)(implicit b: Int)Int

Есть ли способ сделать это, используя синтаксис значения функции?На мгновение игнорируя неявное, я обычно пишу карри-значения функций следующим образом:

scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>

Однако сигнатура функции во втором подходе сильно отличается (каррирование выражается явно).Простое добавление неявного ключевого слова в b не имеет особого смысла, и компилятор также жалуется:

scala> val sum2 = (a: Int) => (implicit b: Int) => a + b
<console>:1: error: '=>' expected but ')' found.
       val sum2 = (a: Int) => (implicit b: Int) => a + b
                                              ^

Кроме того, частичное применение суммы из самого первого подхода для получения значения функции также вызывает проблемы:

scala> val sumFunction = sum _
<console>:14: error: could not find implicit value for parameter b: Int
       val sumFunction = sum _
                         ^

Это наводит меня на мысль, что функции, имеющие неявные параметры, должны иметь указанные параметры, определенные при создании значения функции, а не при последующем применении значения функции.Это действительно так?Можете ли вы когда-нибудь использовать неявный параметр со значением функции?

Спасибо за помощь!

Ответы [ 3 ]

17 голосов
/ 13 июня 2011
scala>  val sum2 = (a: Int) => {implicit b: Int => a + b}
sum2: (Int) => (Int) => Int = <function1>

Это просто сделает b неявным значением для области видимости тела функции, поэтому вы можете вызывать методы, ожидающие неявного Int.

Не думаю, что вы можете иметь неявные аргументыфункции с тех пор неясно, что это за функция.Это Int => Int или () => Int?

Ближайшее, что я нашел:

scala> case class Foo(implicit b: Int) extends (Int => Int) {def apply(a: Int) = a + b}
defined class Foo

scala> implicit val b = 3
b: Int = 3

scala> Foo()
res22: Foo = <function1>

scala> res22(2)
res23: Int = 5
9 голосов
/ 13 июня 2011

В этом фрагменте

scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>

Обратите внимание, что точный тип sum2 равен Function1[Int, Function1[Int, Int]].Он также может быть записан как

val sum2 = new Function1[Int, Function1[Int, Int]] {
    def apply(a: Int) = new Function1[Int, Int] {
        def apply(b: Int) = a + b
    }
}

Теперь, если вы попытаетесь сделать b неявным, вы получите это:

scala>     val sum2 = new Function1[Int, Function1[Int, Int]] {
     |         def apply(a: Int) = new Function1[Int, Int] {
     |             def apply(implicit b: Int) = a + b
     |         }
     |     }
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined
               def apply(a: Int) = new Function1[Int, Int] {
                                       ^

Или, другими словами, Function 'Интерфейсы s не имеют неявных параметров, поэтому все, что имеет неявный параметр, не является Function.

4 голосов
/ 14 июня 2011

Попробуйте перегрузить метод apply.

scala> val sum = new Function1[Int, Function1[Int, Int]] {
         |      def apply(a: Int) = (b: Int) => a + b
         |      def apply(a: Int)(implicit b: Int) = a + b
         |}
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1>

scala> sum(2)(3)
res0: Int = 5

scala> implicit val b = 10
b: Int = 10

scala> sum(2)
res1: Int = 12
...