5

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

最初のものはうまくコンパイルされています。2番目のものはエラーとしてマークされます

4

4 に答える 4

6

Scala言語仕様/式/無名関数(6.23)によると:

無名関数の期待される型がscala.Functionn [ 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

入力値の暗黙的な変換がコンパイルされます。したがって、無名関数の出力に問題があります

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

2番目の暗黙的な変換を使用した可能な修正:

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

このバージョンはコンパイルされます。

于 2012-07-11T21:42:42.230 に答える
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)

コンパイラが両方の暗黙を適切と見なしているように見えます。


2番目の観察:

分割

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 に答える