我想隐式地将函数从A => B
转换为List[A] => List[B]
。
我写了以下隐含的定义:
implicit def lift[A, B](f: A => B): List[A] => List[B] = ...
不幸的是,当我编写以下代码时,不会应用隐式:
val plusOne: (List[Int]) => List[Int] = (x: Int) => (x + 1)
如果我用显式时间注释该函数,它可以正常工作。
为什么呢?我该如何解决?
更新。似乎问题是匿名函数特有的。比较:
@Test
def localLiftingGenerics {
implicit def anyPairToList[X, Y](x: (X, Y)): List[X] => List[Y] = throw new UnsupportedOperationException
val v: List[String] => List[Int] = ("abc", 239)
}
@Test
def localLiftingFuns {
implicit def fun2ListFun[X, Y](f: X => Y): List[X] => List[Y] = throw new UnsupportedOperationException
val v: List[String] => List[Int] = ((x: String) => x.length)
}
第一个编译得很好。第二个标记为错误
答案 0 :(得分:6)
根据The Scala Language Specification /表达式/匿名函数(6.23):
如果匿名函数的预期类型是表单 scala.Function n [ S 1 ,...,S n ,R ], e 是 R ...
因此,函数的结果类型将被推断为List[Int]
,除非您将函数定义与函数值赋值分开(以消除期望的类型):
val function = (x: Int) => (x + 1)
val plusOne: (List[Int]) => List[Int] = function
或明确指定函数类型:
val plusOne: (List[Int]) => List[Int] = ((x: Int) => (x + 1)): Int => Int
答案 1 :(得分:1)
(Scala 2.9.1-1(Java HotSpot(TM)64位服务器VM,Java 1.7.0_05)
第一次观察:如果您复制fun2ListFun
并将其重命名为,例如``fun2ListFun,那么您将获得
found : String => <error>
required: List[String] => List[Int]
Note that implicit conversions are not applicable because they are ambiguous:
both method fun2ListFun2 of type [X, Y](f: X => Y)List[X] => List[Y]
and method fun2ListFun of type [X, Y](f: X => Y)List[X] => List[Y]
are possible conversion functions from String => <error> to List[String] => List[Int]
val v: List[String] => List[Int] = ((x: String) => x.length)
看起来好像编译器认为这两种含义都是适用的。
第二个观察结果:
分裂
val v: List[String] => List[Int] = ((x: String) => x.length) /* Error*/
到
val f = ((x: String) => x.length)
val v: List[String] => List[Int] = f /* Works */
让编译器开心。
答案 2 :(得分:1)
输入值的隐式转换编译。所以我们只对匿名函数
的输出有问题 def localLiftingFuns {
implicit def fun2ListFun[X, Y](f: X => Y): List[X] => Y = throw new UnsupportedOperationException
val v: List[String] => Int = ((x: String) => x.length)
}
使用第二次隐式转换的可能修复:
def localLiftingFuns {
implicit def fun2ListFun[X, Y](f: X => List[Y]): List[X] => List[Y] = throw new UnsupportedOperationException
implicit def type2ListType[X](x:X): List[X] = throw new UnsupportedOperationException
val v: List[String] => List[Int] = ((x: String) => x.length)
}
此版本编译。
答案 3 :(得分:0)
似乎编译器很难确定函数类型的变化。如果你能给他一点帮助,那就行了:
scala> implicit def lift[A,B](f: A => B) = (_:List[A]).map(f)
lift: [A, B](f: (A) => B)(List[A]) => List[B]
scala> val f: List[Int] => List[Int] = ((_:Int) + 1):(Int => Int)
f: (List[Int]) => List[Int] = <function1>