请原谅我,如果已经在别处问过这个问题。我有一个涉及函数值和隐式参数的Scala语法问题。
我很喜欢使用Scala的currying功能。例如,如果我有一个sum函数,并希望使第二个参数隐含:
scala> def sum(a: Int)(implicit b: Int) = a + b
sum: (a: Int)(implicit b: Int)Int
有没有办法使用函数值语法执行此操作?忽略隐含片刻,我通常会写出如下的curried函数值:
scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>
然而,第二种方法中的函数签名是非常不同的(currying正在明确表达)。只是将隐式关键字添加到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 _
^
这使我相信具有隐式参数的函数必须在创建函数值时确定所述参数,而不是在稍后应用函数值时。这是真的吗?你能使用带有函数值的隐式参数吗?
感谢您的帮助!
答案 0 :(得分:17)
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
答案 1 :(得分:9)
在此代码段中
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
的接口没有隐式参数,因此任何带有隐式参数的接口都不是Function
。
答案 2 :(得分:4)
尝试重载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