gpt4 book ai didi

Scala .zip 具有更高种类的类型,奇怪的行为

转载 作者:行者123 更新时间:2023-12-04 18:00:51 26 4
gpt4 key购买 nike

按照Scala methods and higher-kinded type parameters中的问答在我询问如何创建具有更高种类参数的方法以便我可以使用任何 Seq 的地方,我现在在使用 .zip 方法时面临一个奇怪的问题。以下代码无法编译,complire 报告:

Error:(18, 28) type mismatch;
found : Seq[X]
required: S[X]
itrA.zip(itrB).map {

我不知道S[X]在哪里转化为Seq[X]。但是,如果我将调用 .zip 的代码替换为更简单的代码(已注释的代码),它简单地对 itrA 和 itrB 的两个头部求和并返回 ItrA,则编译成功。

代码是:

object SeqOps {

def sum[X: Numeric, S[Y] <: Seq[Y]](s: Seq[S[X]])
(implicit cbf: CanBuildFrom[Nothing, X, S[X]]): Seq[X] =

/*
This code compiles
s.reduce{(itrA, itrB) =>
val num = implicitly[Numeric[X]]
val sum = new num.Ops(itrA.head).+(itrB.head)
itrA
*/

s.reduce{(itrA, itrB) =>
itrA.zip(itrB).map { // it seems that itrB loses the type here :/
case (a, b) =>
val num = implicitly[Numeric[X]]
val sum = new num.Ops(a).+(b)
sum
}

}

def main(args: Array[String]): Unit = {
sum(Seq(Vector(1), Vector(1)))
}

}

问题是:为什么会这样?我该如何解决?

最佳答案

它不知道如果你 zip 两个 S[X] 它可以以某种方式构建一个 S[(X, X)]出来了。为此,您需要一个知道如何构建 S[(X, X)]CBF

不幸的是,似乎没有任何隐式可以构建,例如Vector[Int] 来自通用 Seq[_],因此您需要有关正在构建的集合类型的更多信息。这个想法是具有 -Like 名称的特征可以提供此信息。在这种情况下,SeqLike[X, Repr] 带有 Repr 类型。

如果您现在盯着 signature of zip in SeqLike 看的时间足够长:

def zip
[A1 >: A, B, That]
(that: GenIterable[B])
(implicit bf: CanBuildFrom[Repr, (A1, B), That])
: That

然后你会看到你可以给它一个在第一个组件中有 ReprCBF。所以你可以尝试这样的事情(注意 with SeqLike 和两个 CBF - 一个用于 zip,另一个用于 map):

import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds
import scala.collection.SeqLike

object SeqOps {


def sum[X: Numeric, S[Y] <: Seq[Y] with SeqLike[Y, S[Y]]]
(s: Seq[S[X]])
(implicit
cbf1: CanBuildFrom[S[_], X, S[X]],
cbf2: CanBuildFrom[S[_], (X, X), S[(X, X)]]
)
: Seq[X] = {
val num = implicitly[Numeric[X]]
import num._
s.reduce(_.zip(_)(cbf2).map{ case (a, b) => a + b })
}


def main(args: Array[String]): Unit = {
println(sum(Seq(Vector(1), Vector(1)))) // Vector(2)
println(sum(Seq(List(2, 3), List(4, 5)))) // List(6, 8)
}

}

另一个评论:在某些情况下,将 Nothing 视为 Unobtanium 更容易。如果你的 CBF 需要 Unobtanium 来构建一个 S[X],它可能没有任何用处,因为你想从哪里得到 Unobtanium?

关于Scala .zip 具有更高种类的类型,奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56298632/

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