gpt4 book ai didi

scala - 使用集合来保留类型信息

转载 作者:行者123 更新时间:2023-12-01 07:45:08 24 4
gpt4 key购买 nike

我有一个 Traversable 的以下扩展:

import scala.reflect.ClassTag

object ContainerHelpers {

implicit class TraversableOps[X](a: Traversable[X]) {
def partitionByType[T <: X: ClassTag]: (Traversable[T], Traversable[X]) = {
val (typed, other) = a.partition {
case _: T => true
case _ => false
}
(typed.map(_.asInstanceOf[T]), other)
}

}

// test case:
trait T
case class A(i: Int) extends T

val s = Seq[T](A(0), A(1))
val sa = s.partitionByType[A]
sa // I would like this to be Seq[A], not Traversable[A]

}

该扩展工作正常,但它不保留集合类型 - 它始终返回Traversable。我想编写它,以便 partitionByType 将使用 partitionmap 已知的类型信息,因此类型为 sa 应该是 (Seq[A], Seq[T]),而不是 (Traversable[A], Traversable[T])。我怎样才能做到这一点,也许使用更高级的类型,或者类似的东西?

最佳答案

您可以使用 CanBuildFrom 自行构建集合,而不是依赖 TraversableLike 的实现,然后将其丢弃。这 其优点是不在任何地方进行任何转换,而且它不会比替代方案花费更多的费用,因为 TraversableLike 中的 partition 方法具有相同的作用。

这是获得您想要的东西的第一次尝试(为了清楚起见,我更改了参数化类型的名称):

implicit class TraversableOps[Elem, T[_Ignore] <: Traversable[_Ignore]](a: T[Elem]) {
def partitionByType[Target <: Elem: ClassTag]
(implicit cbf1: CanBuildFrom[T[Elem], Elem, T[Elem]],
cbf2: CanBuildFrom[T[Target], Target, T[Target]]) : (T[Target], T[Elem]) = {

val l = cbf2()
val r = cbf1()

for (x <- a) x match{
case t: Target => l += t
case _ => r += x
}

(l.result, r.result)
}
}

它适用于以下测试用例:

// test case:
trait A
trait B extends A
case class T(i: Int) extends A
case class U(i: Int) extends B

val s1 : List[A] = List(T(0), U(1))
val s2 : Seq[A] = List(T(0), U(1))

val sa1 = s1.partitionByType[T] //sa1 : (List[T], List[A]) = (List(T(0)),List(U(1)))
val sa2 = s2.partitionByType[T] //sa2 : (Seq[T], Seq[A]) = (List(T(0)),List(U(1)))

关于scala - 使用集合来保留类型信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46050179/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com