5

我想将函数从隐式转换A => BList[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)
}

第一个编译得很好。第二个被标记为错误

4

4 回答 4

6

根据Scala 语言规范/表达式/匿名函数(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
于 2012-07-12T09:51:52.240 回答
1

The implicit conversion for the input value compiles. So we just have a problem for the output of the anonymous function

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

A possible fix using a second implicit conversion:

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

This version compiles.

于 2012-07-11T21:42:42.230 回答
1

(Scala 2.9.1-1 (Java HotSpot(TM) 64-Bit Server 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 */

使编译器高兴。

于 2012-07-11T21:37:47.293 回答
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>
于 2012-07-12T08:35:26.427 回答