Scala 如何使用隐式转换将列表[a]转换为列表[B]

Scala 如何使用隐式转换将列表[a]转换为列表[B],scala,scalaz,Scala,Scalaz,我的代码中经常出现以下用例: 收藏 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) } 在Scala中,最优雅的方式是什么,也许是在Scalaz的帮助下实现的 编辑:我的

我的代码中经常出现以下用例:

  • 收藏
  • 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)
  }
在Scala中,最优雅的方式是什么,也许是在Scalaz的帮助下实现的


编辑:我的问题的目标是找到一种惯用的方法,这是库/开发人员之间的常用方法。从这个意义上说,开发我自己的pimp my library解决方案是我不喜欢的,因为编写我的代码的其他人不知道这种转换的存在,也不会使用它,他们会重写自己的。我倾向于使用库方法来实现这种常见的函数,这就是为什么我想知道Scalaz中是否存在这样的功能。

如果您知道这些类型,这是非常简单的。从
A
B
的第一次隐式转换:

implicit def conversion(a: A): B = //...
然后需要从
List[S]
List[T]
的隐式转换,其中
S
T
是存在从
S
T
的隐式转换的任意类型:

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
T
B
,我不会在这里使用隐式转换,而是在类中绑定视图:

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

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

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

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)

这里不使用另一个隐式转换,我可能会使用一个typeclass,但我想您已经了解了基本思想。

从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]

在我的代码中,我使用了一个更通用的版本,该版本改编自上面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]]
/**元素可转换的可遍历实例的隐式转换*/
隐式def convTrav[S,T,I[S]T:I[T]=
(输入映射c).asInstanceOf[I[T]]

(这对我很有用,尽管我很想知道是否有更有经验的Scala程序员出于任何原因认为这是一个坏主意,除了关于隐式转换的常见警告)

它是某些标准库的一部分吗?我讨厌重新发明wheel@Edmondo1984:不知道,我刚刚白手起家写的,但我可能也在重新发明轮子。顺便说一句,我再次阅读了我的答案,我生成了解决方案,所以对于任何可转换类型,您只需要一个
convList
隐式转换。我知道,我只是指出在回答中明确这一点是有益的
/** 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]]