List[Int]
があり、各要素でtoString
を呼び出して、結果をVector[String]
として返したいとします。
Scalaでこれを行うためのさまざまな方法は何ですか?最小限の量の明示的な型付けの解決策はありますか? —つまり、Vector
ではなくList
が必要であることを指定したいのですが、String
引数をフィルター関数から推測したいのですが。
または、CanBuildFrom
インスタンスを明示的に渡す必要がありますか? Seq
s、Set
sおよびMap
sの場合、これらはどこから入手できますか?
breakOut
をCanBuildFrom
として使用し、タイパーに結果のタイプを指定します(残念ながら、ここで文字列を指定する必要があります)
scala> import collection.breakOut
import collection.breakOut
scala> List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)
scala> res0.map(_.toString)(breakOut) : Vector[String]
res2: Vector[String] = Vector(1, 2, 3)
Scala 2.10.0は、コレクションを別のコレクションに変換する簡単な方法を導入しました:
scala> List(1, 2, 3).map(_.toString).to[Vector]
res0: Vector[String] = Vector(1, 2, 3)
または、IndexedSeq
を明示的に要求します。
scala> res0.map(_.toString).toIndexedSeq
res4: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3)
中間List
を作成せずにこれを行う場合は、次のようにします。
scala> res0.view.map(_.toString).toIndexedSeq
res5: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3)
自然変形を使用して(ぎこちなく、より一般的には)できます。
scala> trait Trans[F[_], G[_]] {
| def f2g[A](f : F[A]) : G[A]
| }
defined trait Trans
次に、リストから型クラスのインスタンスを提供します〜>ベクトル変換:
scala> implicit val List2Vector = new Trans[List, collection.immutable.Vector] {
| def f2g[A](l : List[A]) : Vector[A] = l.map(identity[A])(collection.breakOut)
| }
List2Vector: Java.lang.Object with Trans[List,scala.collection.immutable.Vector] = $anon$1@56329755
ラッパーと暗黙の変換を定義します。
scala> class Clever[M[_], A](ma : M[A]) { def to[N[_]](implicit t : Trans[M, N]) : N[A] = t.f2g(ma) }
defined class Clever
scala> implicit def ma2clever[M[_], A](ma : M[A]) = new Clever[M, A](ma)
ma2clever: [M[_],A](ma: M[A])Clever[M,A]
次に:
scala> List(1, 2, 3).map(_.toString).to[Vector]
res4: Vector[Java.lang.String] = Vector(1, 2, 3)