如何使用隐式转换将List [A]转换为List [B]

Edm*_*984 8 scala scalaz

我有以下用例,通常在我的代码中出现:

  • 收藏[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)
  }
Run Code Online (Sandbox Code Playgroud)

在Scala中最优雅的方法是什么,也许在Scalaz的帮助下做同样的事情?

编辑:我的问题的目标是找到一种惯用的方式,这是图书馆/开发者之间的共同方法.在这种意义上,开发我自己的pimp-my-library解决方案是我不喜欢的,因为编写我的代码的其他人不会知道这种转换的存在并且不会使用它,并且他们将重写他们自己的.我赞成使用库方法来实现这个常见功能,这就是为什么我想知道Scalaz中是否存在这样的功能.

Tom*_*icz 14

如果你知道类型,这是非常简单的.第一次隐式转换AB:

implicit def conversion(a: A): B = //...
Run Code Online (Sandbox Code Playgroud)

那么你需要从隐式转换List[S]List[T]哪里S,并T可以是任意类型,其隐式转换从ST存在:

implicit def convList[S, T](input: List[S])(implicit c: S => T): List[T] = 
   input map c
Run Code Online (Sandbox Code Playgroud)

这应该工作:

val listOfA: List[A] = //...
val listOfB: List[B] = listOfA
Run Code Online (Sandbox Code Playgroud)

这由编译器解决:

val listOfB: List[B] = convList(listOfA)(conversion)
Run Code Online (Sandbox Code Playgroud)

这里SATB.


dre*_*xin 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)
}
Run Code Online (Sandbox Code Playgroud)

您现在可以创建一个Items包含列表的实例,Foo并在内部使用它们,就像它们是Bars一样.

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

scala> res8(0)
res9: Bar = Bar(1)
Run Code Online (Sandbox Code Playgroud)

编辑:

关于为什么我不使用隐式转换的一些澄清:

隐式转换可能是危险的,当它们在范围内并意外转换时,它们不应转换.我总是明确地或通过视图边界转换内容,因为我可以控制它,隐式转换也可能缩小代码的大小,但也使其他人更难理解.我只会对'扩展我的库'模式使用隐式转换.

编辑2:

但是,如果此类方法在范围内,则可以向集合类型添加一个方法来执行此转换:

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)
Run Code Online (Sandbox Code Playgroud)

我可能不会在这里使用另一个隐式转换,而是使用类型类,但我认为你得到了基本的想法.