20

暗黙の変換があるとしましょう:

implicit def aToB(a: A):B={
...
}

この暗黙の変換をリストの要素で機能させるにはどうすればよいですか?

私が持っている場合:

val listOfA: List[A] ...

そして私はBのリストを受け取る関数を持っていますが、Scalaにすべての要素をAからBに暗黙的に変換させることは可能ですか?

暗黙的な変換がない場合、変換は次のようになります。

lisftOfA.map(a => new B(a.someValue, a.anotherValue))

しかし、私はこれが「魔法」のように起こることを望んでいます...それは質問するには多すぎます。

4

4 に答える 4

18

検討したいいくつかの選択肢を次に示します。

1.ビューバウンドを使用する

Bのリストを取得する関数を変更できる場合、これが最も簡単な解決策になります。Bに変換できるもののリストを受け入れるように変更します。あれは、

def yourFn(l: List[B]) = ...

になります

def yourFn[X <% B](l: List[X]) = ...

次に、listOfAを使用して関数を呼び出すことができます。

yourFn(listOfA)

2.変換方法を紹介します

これは、外部変換が暗黙的でないことを除いて、Rogachの最初のソリューションに似ています。

def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }

次に、関数の呼び出しサイトで、次のように記述します。

yourFn(convert(listOfA))

Rogachの2番目のソリューションと同様に、これは暗黙的な変換を行うよりも少し安全です。

3.暗黙の変換を導入します

これはRogachの最初のソリューションと同等ですが、表記は少し優れています(IMO)。

implicit def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }

この変換が呼び出しサイトの範囲内にある場合は、listOfAを使用して関数を呼び出すことができます。

yourFn(listOfA)

別れの考え

この問題を一般的な方法で解決する方法を検討するのは興味深いことです。メソッドを実装する任意の型を処理できるように変換メソッドを定義したい場合はどうなりますmapか?すなわち、

def convert[B, A <% B, C[_]](c: C[A]): C[B] = c map { a => a: B }

もちろん、これは機能しません。署名には、C実装する必要のある制約を表すものがないためmapです。私の知る限り、この制約の表現はかなり複雑であり、を実装するすべてのタイプにすぐに使用できるサポートを提供する方法で行うことはできませんmapタイプセーフなScalaシーケンス内包表記を参照してください。

于 2012-09-16T23:23:47.937 に答える
4

以下は一般的な解決策であり、スコープで暗黙的な変換A => Bが使用可能な場合に、リストの暗黙的な変換(List [A] => List [B])を有効にします。

scala> class A
defined class A

scala> class B
defined class B

scala> implicit def a2b(a:A) = new B
a2b: (a: A)B

scala> implicit def mapI[A,B](l: List[A])(implicit conv: A => B): List[B] = l.map(conv)
mapI: [A, B](l: List[A])(implicit conv: (A) => B)List[B]

scala> List(new A): List[B]
res0: List[B] = List(B@efa0bf4)

これはあなたが必要なものですか?

また、すでにその暗黙の変換があるので、次のように書くことができます。

listOfA.map(a2b) // List[B]

それはもう少し冗長になりますが、コードをもう少し明示的に制御できます。

于 2012-09-16T15:15:07.850 に答える
3

可能な限り最高だと思います

implicit def asToBs(as: List[A]): List[B] = as map aToB
于 2012-09-16T15:16:52.080 に答える
1

完全を期すために、を使用するより一般的なアプローチを検討することをお勧めしますCanBuildFrom

このプログラム:

import scala.collection.generic.CanBuildFrom
import scala.language.{higherKinds, implicitConversions}

implicit def implyConvertedTraversable[A, B, C[X] <: Traversable[X]](as: C[A])(implicit conversion: A => B, cbf: CanBuildFrom[C[A], B, C[B]]): C[B] = {
  val builder = cbf(as)
  builder.sizeHint(as)
  builder ++= as.map(conversion)
  builder.result()
}

implicit def implyString(a: Int): String = a.toString

val intList = List(1, 2, 3)
val intStream = Stream(1, 2, 3)

val stringList: List[String] = intList
val stringStream: Stream[String] = intStream

収量:

intList: List[Int] = List(1, 2, 3)
intStream: scala.collection.immutable.Stream[Int] = Stream(1, ?)

stringList: List[String] = List(1, 2, 3)
stringStream: Stream[String] = Stream(1, ?)
于 2016-06-22T22:21:26.537 に答える