8

私のコードで頻繁に発生する次のユースケースがあります。

  • コレクション[A]
  • A から B への暗黙的な変換

B のコレクションを取得したいのですが、次のように暗黙的に使用できます。

  case class Items(underlying:List[B])
  import B._
  def apply(a:List[A]):Items = {
    val listOfB= a.map {implicitly[A=>B]}
    Items(listOfB)
  }

おそらく同じことをするScalazの助けを借りて、Scalaでそれを行う最もエレガントな方法は何ですか?

編集:私の質問の目標は、ライブラリ/開発者の間で一般的なアプローチである慣用的な方法を見つけることです。そのような意味で、自分の pimp-my-library ソリューションを開発することは嫌いです。なぜなら、私のコードを書いている他の人は、この変換の存在を知らず、それを使用せず、自分自身を書き換えるからです。私はこの一般的な関数にライブラリ アプローチを使用することを好みます。そのため、Scalaz にそのような機能が存在するかどうか疑問に思っています。

4

4 に答える 4

14

種類さえわかれば簡単です。Aからへの最初の暗黙的な変換B:

implicit def conversion(a: A): B = //...

次に、 からどこへの暗黙的な変換が必要であり、 からへList[S]の暗黙的な変換が存在する任意の型です。List[T]STST

implicit def convList[S, T](input: List[S])(implicit c: S => T): List[T] = 
   input map c

これでうまくいくはずです:

val listOfA: List[A] = //...
val listOfB: List[B] = listOfA

これは、コンパイラによって次のように解決されます。

val listOfB: List[B] = convList(listOfA)(conversion)

どこSとです. A_TB

于 2013-02-18T17:26:23.257 に答える
9

ここでは暗黙的な変換は使用しませんが、クラスにバインドされたビューを使用します。

case class Foo(x: Int)
case class Bar(y: Int)
implicit def foo2Bar(foo: Foo) = Bar(foo.x)
case class Items[A <% Bar](xs: List[A]) {
  def apply(x: Int): Bar = xs(x)
}

Itemsのリストを使用して のインスタンスを作成し、FooそれらをBarのように内部的に使用できるようになりました。

scala> Items(List(Foo(1)))
res8: Items[Foo] = Items(List(Foo(1)))

scala> res8(0)
res9: Bar = Bar(1)

編集

暗黙の変換を使用しない理由についての説明:

暗黙的な変換は、スコープ内にあり、誤って変換してはならないものを変換する場合、危険な場合があります。私は常に明示的に、またはビュー境界を介して何かを変換します。これは、それを制御できるためです。また、暗黙的な変換によりコードのサイズが縮小される可能性がありますが、他の人にとっては理解しにくくなります。「ライブラリの拡張」パターンには暗黙的な変換のみを使用します。

edit2 :

ただし、そのようなメソッドがスコープ内にある場合は、この変換を行うメソッドをコレクション型に追加できます。

trait Convertable[M[A], A] {
  def convertTo[B](implicit f: A => B): M[B]
}

implicit def list2Convertable[A](xs: List[A]) = new Convertable[List, A] {
  def convertTo[B](implicit f: A => B) = xs.map(f)
}

scala> implicit def int2String(x: Int) = x.toString
int2String: (x: Int)String

scala> List(1,2,3).convertTo[String]
res0: List[String] = List(1, 2, 3)

ここで別の暗黙的な変換を使用する代わりに、代わりに型クラスを使用することになるでしょうが、基本的な考え方は理解できたと思います。

于 2013-02-18T17:31:07.127 に答える
2

Scala 2.10以降で動作します:

implicit class ListOf[A](val list: List[A]) { 
  def of[B](implicit f: A => B): List[B] = list map f 
}
implicit def int2String(i: Int) = i.toString

// Usage
List(1,2,3).of[String]
于 2013-02-18T21:02:10.227 に答える
-1

私のコードでは、すべてのTraversableインスタンスを処理する上記のTomaszのソリューションから適応したより一般的なバージョンを使用しています

/** Implicit conversion for Traversable instances where the elements are convertable */
implicit def convTrav[S, T, I[S] <: Traversable[S]](input: I[S])(implicit c: S => T): I[T] =
  (input map c).asInstanceOf[I[T]]

(これは私にとってはうまくいっていますが、経験豊富な Scala プログラマーが暗黙の変換に関する通常の警告を除いて、何らかの理由でこれが悪い考えであると考えているかどうかを知りたいと思っています)

于 2013-06-07T07:32:18.313 に答える