2012-07-11 172 views
5

我想隐式地将函数A => B转换为List[A] => List[B]隐式提升scala

我写了下面隐含的定义:

implicit def lift[A, B](f: A => B): List[A] => List[B] = ... 

不幸的是,当我写了下面的代码,含蓄不适用:

val plusOne: (List[Int]) => List[Int] = (x: Int) => (x + 1) 

如果我注释有明确时间的功能,工作正常。

为什么?我该如何解决它?

UPDATE。看来这个问题是特定于匿名函数的。比较:

@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

您可以提供用于实现“隐式def”的代码吗? – 2012-07-11 21:25:23

+1

@ChrisJamesC更新了测试用例 – 2012-07-11 21:28:02

+2

您确定您需要/想要这样做吗? “地图”为少数人物购买了很多清晰的内容,例如'val plusOne:(List [Int])=> List [Int] = _ map(_ + 1)'实际上比您的版本短。 – 2012-07-11 21:53:29

回答

6

根据The Scala Language Specification /表达式/匿名函数(6.23):

如果预期的类型的匿名函数的形式为 scala。功能Ñ [小号,&hellip,S Ñ,R],期望的类型Ë的是- [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

(斯卡拉2.9.1-1(Java的热点(TM)64位服务器VM,爪哇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) 

看起来好像编译器会同时考虑implicits适用。


第二观察:

拆分

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 */ 

使编译器高兴。

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) 
} 

该版本编译。

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>