gpt4 book ai didi

scala - 将 scala 2.13 中的自定义集合操作添加到特定类型的任意集合

转载 作者:行者123 更新时间:2023-12-04 16:28:47 25 4
gpt4 key购买 nike

注意 - 下面描述的操作现在作为 partitionMap 存在于标准库中,但我相信关于如何实现更通用的目标仍然是一个有效的问题

关于 scala 2.13 的问题 - 在我需要限制输入集合的元素类型的地方添加自定义集合操作时,如何使用/构造特定类型的集合?例如我如何定义:

def split[CC[_], A, B](coll: CC[Either[A, B]]): (CC[A], CC[B])

documentation 之后我已经设法实现了以下目标:

import collection.generic.IsIterable
import scala.collection.{BuildFrom, Factory}

class SplitOperation[Repr, S <: IsIterable[Repr]](coll: Repr, itr: S) {
def split[A, B, AS, BS](
implicit bfa: BuildFrom[Repr, A, AS],
bfb: BuildFrom[Repr, B, BS],
ev: itr.A =:= Either[A, B]): (AS, BS) = {

val ops = itr(coll)
val as = bfa.fromSpecific(coll)(ops.iterator.map(ev).collect { case Left(a) => a })
val bs = bfb.fromSpecific(coll)(ops.iterator.map(ev).collect { case Right(b) => b })

(as, bs)
}
}

implicit def SplitOperation[Repr](coll: Repr)(implicit itr: IsIterable[Repr]): SplitOperation[Repr, itr.type] =
new SplitOperation(coll, itr)

但是,我需要在使用地点提供类型,否则我会得到不同的隐式扩展。

scala> List(Left("bah"), Right(1), Left("gah"), Right(2), Right(3))
res1: List[scala.util.Either[String,Int]] = List(Left(bah), Right(1), Left(gah), Right(2), Right(3))

scala> res1.split
^
error: diverging implicit expansion for type scala.collection.BuildFrom[List[scala.util.Either[String,Int]],A,AS]

但以下工作:

scala> res1.split[String, Int, List[String], List[Int]]
res4: (List[String], List[Int]) = (List(bah, gah),List(1, 2, 3))

编辑

class SplitOperation[X, CC[_], S <: IsIterable[CC[X]]](coll: CC[X], itr: S) {
def split[A, B](implicit bfa: BuildFrom[CC[X], A, CC[A]], bfb: BuildFrom[CC[X], B, CC[B]], ev: itr.A =:= Either[A, B]): (CC[A], CC[B]) = {
val ops = itr(coll)
val as = bfa.fromSpecific(coll)(ops.iterator.map(ev).collect { case Left(a) => a })
val bs = bfb.fromSpecific(coll)(ops.iterator.map(ev).collect { case Right(b) => b })

(as, bs)
}
}

implicit def SplitOperation[A, B, CC[_]](coll: CC[Either[A, B]])(implicit itr: IsIterable[CC[Either[A, B]]]): SplitOperation[Either[A, B], CC, itr.type] =
new SplitOperation(coll, itr)

给我一​​点改进。现在我只需要在调用站点提供类型参数 AB:

scala> l.split[String, Int]
res2: (List[String], List[Int]) = (List(bah, gah),List(1, 2))

最佳答案

这似乎有效:

class SplitOperation[A, B, CC[_], S <: IsIterable[CC[Either[A, B]]]](coll: CC[Either[A, B]], itr: S) {
def split(implicit bfa: BuildFrom[CC[Either[A, B]], A, CC[A]], bfb: BuildFrom[CC[Either[A, B]], B, CC[B]], ev: itr.A =:= Either[A, B]): (CC[A], CC[B]) = {
val ops = itr(coll)
val as = bfa.fromSpecific(coll)(ops.iterator.map(ev).collect { case Left(a) => a })
val bs = bfb.fromSpecific(coll)(ops.iterator.map(ev).collect { case Right(b) => b })

(as, bs)
}
}

implicit def SplitOperation[A, B, CC[_]](coll: CC[Either[A, B]])(implicit itr: IsIterable[CC[Either[A, B]]]): SplitOperation[A, B, CC, itr.type] =
new SplitOperation(coll, itr)

关于scala - 将 scala 2.13 中的自定义集合操作添加到特定类型的任意集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56542335/

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