如何解决Scala 2.13:返回相同的集合类型甚至数组和字符串
这是一个 faro shuffle 的基本实现。这是一个out-shuffle(“faro out,伙计!”)只是因为它比in-shuffle更容易编码。
def faroOut[A](cards: List[A]): List[A] =
List.unfold(cards.splitAt((cards.size + 1) / 2)) {
case (a,b) => Option.when(a.nonEmpty)(a.head -> (b,a.tail))
}
faroOut(List("AS","KD","QC","JH","2S","3D","4C","5H"))
//res0: List[String] = List(AS,2S,KD,3D,QC,4C,JH,5H)
faroOut(List(1,2,3,4,5,6,7))
//res1: List[Int] = List(1,7,4)
这在其元素类型上是通用的,但在其集合类型上不是。让我们尝试解决这个问题。
import scala.collection.Factory
def faroOut[A,CC[x] <: Iterable[x]](cards:CC[A]
)(implicit fac: Factory[A,CC[A]]
): CC[A] =
Iterator.unfold(cards.splitAt((cards.size + 1) / 2)) {
case (a,a.tail))
}.to(fac)
faroOut(LazyList("AS","5H"))
faroOut(Vector(1,7))
//faroOut(Array(3,6)) <-- won't compile
将其转换为扩展方法并不太复杂,但这不需要我们在这里关注。
所以这适用于列表和向量,但不适用于 Array
或 String
,因为它们来自 Java 领域,而不是 Scala Iterable
层次结构的一部分。为此,我们需要引入 IsSeq
类型类。
有趣的是,这在 Scala-3 中非常简单。
import scala.collection.generic.IsSeq
import scala.collection.Factory
def faroOut[Repr](cards: Repr
)(using seq: IsSeq[Repr],fac: Factory[seq.A,Repr]): Repr =
val seqOps = seq(cards).toIterable
Iterator.unfold(seqOps.splitAt((seqOps.size + 1) / 2)) {
case (a,a.tail))
}.to(fac)
这是一个 Scastie to prove it。
将其转换为扩展方法几乎是微不足道的,但这不需要我们在这里关心。
请注意 Factory[_,_]
的第一个类型参数如何依赖于参数组中的前一个参数。 Scala-2 上不可能有一个很酷的 Scala-3 增强功能。
在 Scala docs page 和 this SO Q/A 上花了一些时间后,我只剩下 QUESTION (at long last) : 没有更小和/或更简单的解决方案吗?我们真的需要把它变成一个包含所有 implicit
转换等的扩展方法吗?
解决方法
要在单参数列表限制内绕过 Scala 2 依赖类型,请尝试类型细化
IsIterable[Repr] { type A = E }
或 Aux 类型别名模式
type AuxA[Repr,E] = IsIterable[Repr] { type A = E }
例如
def faroOut[Repr,E](cards: Repr)(
implicit
seq: IsIterable[Repr] { type A = E },fac: Factory[E,Repr]
): Repr = {
val seqOps = seq(cards).toIterable
Iterator.unfold(seqOps.splitAt((seqOps.size + 1) / 2)) {
case (a,b) => Option.when(a.nonEmpty)(a.head -> (b,a.tail))
}.to(fac)
}
faroOut(Array(3,4,5,6)) // : Array[Int] = Array(3,6)
faroOut("ABCxyz") // : String = AxByCz
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。