简体   繁体   English

如何使用我自己的通用`map`(正确的方法)来丰富Scala集合?

[英]How to enrich Scala collections with my own generic `map` (the right way)?

I'm trying to enrich Scala collections with my own map method, and I'm close but the implicit conversion doesn't work. 我正在尝试用我自己的map方法来丰富Scala集合,我很接近,但隐式转换不起作用。 Besides that, is there anything else I'm missing here? 除此之外,还有什么我在这里不见了吗? I'm looking at various other resources on the Web, including SO answers that this question is being marked as duplicating , and many are missing something here and there (eg using C[A] <: GenTraversable[A] , using b() instead of b(xs) , forgetting about Array , forgetting about BitSet , etc.). 我正在寻找Web上的各种其他资源, 包括这个问题被标记为重复的SO答案 ,并且许多人在这里和那里都缺少某些东西(例如使用C[A] <: GenTraversable[A] ,使用b()而不是b(xs) ,忘记了Array ,忘记了BitSet等等。

implicit def conv[A,C](xs: C)(implicit ev: C <:< GenTraversableLike[A,C]) = new {
  def mymap[B,D](f: A => B)(implicit b: CanBuildFrom[C,B,D]): D = b(xs).result // placeholder
}

scala> conv(List(1,2,3))
res39: java.lang.Object{def mymap[B,D](f: Int => B)(implicit b: scala.collection.generic.CanBuildFrom[List[Int],B,D]): D} = $$$$2c9d7a9074166de3bf8b66cf7c45a3ed$$$$anon$1@3ed0eea6

scala> conv(List(1,2,3))mymap(_+1)
res40: List[Int] = List()

scala> conv(BitSet(1,2,3))mymap(_+1)
res41: scala.collection.immutable.BitSet = BitSet()

scala> conv(BitSet(1,2,3))mymap(_.toFloat)
res42: scala.collection.immutable.Set[Float] = Set()

scala> List(1,2,3)mymap(_+1)
<console>:168: error: Cannot prove that List[Int] <:< scala.collection.IterableLike[A,List[Int]].
              List(1,2,3)mymap(_+1)
                  ^

scala> implicit def conv[A, C](xs: C)(implicit ev: C => GenTraversable[A]) = new {
     | def mymap[B,D](f: A => B)(implicit b: CanBuildFrom[GenTraversable[A],B,D]): D =
     | xs map f
     | }
conv: [A, C](xs: C)(implicit ev: C => scala.collection.GenTraversable[A])java.lang.Object{def mymap[B,D](f: A => B)(implicit b: scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[A],B,D]): D}

scala> conv(Array(1)) mymap (_+1)
res6: scala.collection.GenTraversable[Int] = ArrayBuffer(2)

scala> Array(1) mymap (_+1)
<console>:68: error: No implicit view available from Array[Int] => scala.collection.GenTraversable[A].
              Array(1) mymap (_+1)
                   ^

I've answered this very question about type inference just last week. 我上周刚回答了关于类型推断的这个问题 Here's the code: 这是代码:

implicit def conv[A,C <: GenTraversable[A]](xs: C with GenTraversableLike[A,C]) = new {
  def mymap[B,D](f: A => B)(implicit b: CanBuildFrom[C,B,D]): D = {
    val builder = b(xs)
    xs foreach { x => builder += f(x) }
    builder.result
  }
}

I could have used GenTraversable instead of GenTraversableLike in this particular case. 在这种特殊情况下,我本可以使用GenTraversable而不是GenTraversableLike I prefer the later because it offers more. 我更喜欢后者,因为它提供更多。

The problem is that declaring [A, C <: GenTraversable[A]] does not instruct Scala to infer the type of A from the type of C . 问题在于声明[A, C <: GenTraversable[A]] 并不指示Scala从C类型推断出A的类型。 Types are inferred based on how they are used in the parameters, and then checked against the boundaries specified by the type parameters. 类型是根据它们在参数中的使用方式推断出来的,然后根据类型参数指定的边界进行检查。

So when I write xs: C with GenTraversable[A] , I let Scala know it should infer A from xs . 因此,当我xs: C with GenTraversable[A]编写xs: C with GenTraversable[A] ,我让Scala知道它应该从xs推断出A And writing GenTraversableLike[A, C] tells Scala it should pick a collection that returns C for methods that return the same collection. 编写GenTraversableLike[A, C]告诉Scala它应该选择一个返回 C的集合来返回相同集合的方法。 This means you can call filter and get C back, instead of getting GenTraversable back. 这意味着您可以调用filter并获取C ,而不是返回GenTraversable

As for wishing to include views, that I don't know how you could accomplish. 至于希望包含观点,我不知道你将如何完成。

I have answered a similar question here . 在这里回答了类似的问题。 You can also refer to this thread where Rex Kerr explains how to perform such pimping in general. 您也可以参考这个线程 ,其中Rex Kerr解释了如何执行这样的拉皮条。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM