scala - 通用微风向量法

标签 scala generics vector scala-breeze

我正在尝试实现一个通用的 Scala 方法,用于处理类型为 Float 或 Double 的 Breeze 向量(至少,特异性较低是一个优点)。 这是 Vector[Double] 的一个简单示例:

def vectorSum(vectors: Seq[Vector[Double]]): Vector[Double] = {
  vectors.reduce { (v1, v2) => v1 :+ v2 }
}

我对 Scala 和 Breeze 有点陌生,所以我的天真的方法是:

def vectorSumGeneric[T <: AnyVal](vectors: Seq[Vector[T]]): Vector[T] = {
  vectors.reduce { (v1, v2) => v1 :+ v2 }
}

但是,这会引发以下编译错误:

  • diverging implicit expansion for type breeze.linalg.operators.OpAdd.Impl2[breeze.linalg.Vector[T],breeze.linalg.Vector[T],That] starting with method v_v_Idempotent_OpAdd in trait VectorOps
  • not enough arguments for method :+: (implicit op: breeze.linalg.operators.OpAdd.Impl2[breeze.linalg.Vector[T],breeze.linalg.Vector[T],That])That. Unspecified value parameter op.

我尝试过一些变体,包括 T <% AnyValT <% Double ,但它们也不起作用(可能如预期的那样)。 Scala 类型边界文档没有给我关于这样的用例的线索。 解决这个问题的正确方法是什么?

最佳答案

问题在于类型参数 T 可以是任何内容,但您必须确保您的类型 T 至少支持加法作为代数运算。如果T是半环,那么您可以添加两个T类型的元素。您可以通过指定上下文绑定(bind)来强制 T 为半环:

def vectorSum[T: Semiring](vectors: Seq[Vector[T]]): Vector[T] = {
  vectors.reduce(_ + _)
}

这样,您就可以强制执行 T 的每个实例化,您的作用域中也有一个定义加法操作的 Semiring[T]。 Breeze 已经为所有支持加法的原始类型定义了这个结构。

如果您想支持更多代数运算(例如除法),那么您应该将类​​型变量限制为具有 Field 上下文绑定(bind)。

def vectorDiv[T: Field](vectors: Seq[Vector[T]]): Vector[T] = {
  vectors.reduce(_ / _)
}

如果您想支持向量上的通用逐元素二元运算:

def vectorBinaryOp[T](
    vectors: Seq[Vector[T]], op: (T, T) => T)(
    implicit canZipMapValues: CanZipMapValues[Vector[T], T, T, Vector[T]])
  : Vector[T] = {
  vectors.reduce{
    (left, right) => implicitly[CanZipMapValues[Vector[T], T, T, Vector[T]]].map(left, right, op)
  }
}

然后你可以在向量上定义任意二元运算:

val vectors = Seq(DenseVector(1.0,2.0,3.0,4.0), DenseVector(2.0,3.0,4.0,5.0))
val result = VectorSum.vectorBinaryOp(vectors, (a: Double, b: Double) => (a / b))

关于scala - 通用微风向量法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31919356/

相关文章:

java - ImageView vector 资源在 Nougat 上工作但在 Oreo 上崩溃

c++ - 完全释放 std::vector 容器的内存

bash - Shebang "#!"开始和 "!#"结束?

scala - 错误 : could not find implicit value for parameter timeout: akka. util.Timeout

scala - Scala中列表的局部最大值

c# - 优化 list<T>.Sort(Comparer)

Java 泛型转换为通配符规则

java - Tomcat 7 中的 Finatra

java - 如何返回参数化返回类型的子类,其参数类型是返回类型参数类型的子类?

c++ - 试图反射(reflect)对原始变量更改的影响(通过引用调用)