25

请原谅我是否已经在其他地方问过这个问题。我有一个涉及函数值和隐式参数的 Scala 语法问题。

我很乐意使用 Scala 的柯里化功能的隐式。例如,如果我有一个 sum 函数并希望将第二个参数设为隐式:

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
                                              ^

此外,从第一种方法中部分应用 sum 来获得函数值也会导致问题:

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

这使我相信具有隐式参数的函数必须在创建函数值时确定所述参数,而不是在稍后应用函数值时确定。真的是这样吗?你可以使用带有函数值的隐式参数吗?

谢谢您的帮助!

4

3 回答 3

19
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
于 2011-06-13T03:11:05.657 回答
9

在这个片段中

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

请注意,精确的类型sum2Function1[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的接口没有隐式参数,所以任何带有隐式参数的东西都不是Function.

于 2011-06-13T03:47:54.080 回答
5

尝试重载 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
于 2011-06-14T15:12:58.750 回答