2012-07-11 161 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>