gpt4 book ai didi

scala - 在 Scala 中实现通用向量

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

我正在尝试在 Scala 中实现一个通用(数学)向量,但我遇到了一些如何正确执行的问题:

1)你如何处理 + 和 - 使得对 Vector[Int]Vector[Double] 的操作会返回一个 Vector[Double] ?简而言之,我将如何进行数字类型的自动提升(最好利用 Scala 的自动提升)?因为使用 implicit n: Numeric[T] 仅在两个向量的类型相同时才有效。

2)相关,我应该如何定义 * 操作,使其接受任何数字类型,并返回正确数字类型的向量?也就是说, Vector[Int] * 2.0 将返回 Vector[Double]

这是我当前的代码(它的行为不像我想要的那样):

case class Vector2[T](val x: T, val y: T)(implicit n: Numeric[T]) {
import n._

def length = sqrt(x.toDouble() * x.toDouble() + y.toDouble() * y.toDouble())
def unary_- = new Vector2(-x, -y)

def +(that: Vector2) = new Vector2(x + that.x, y + that.y)
def -(that: Vector2) = new Vector2(x - that.x, y - that.y)

def *(s: ???) = new Vector2(x * s, y * s)
}

更新

经过深思熟虑,我决定接受 Chris K 的回答,因为它适用于我问过的所有情况,尽管类型类解决方案很冗长(Scala 中的数字类型是 Byte、Short、Int, Long、Float、Double、BigInt、BigDecimal,这使得在每个可能的类型对之间实现所有操作变得非常有趣)。

我对这两个答案都投了赞成票,因为它们都是很好的答案。我真的希望 Gabriele Petronella 的答案适用于所有可能的情况,因为它是一个非常优雅和简洁的答案。我确实希望它最终会以某种方式起作用。

最佳答案

想到了几种方法:

  • 使用类型类,示例如下
  • 使用 Spire,一个 Scala 的数学库。可以找到使用 spire 的矢量教程 here
  • 将类型类与 Shapeless 组合以支持任何维度的向量。阅读 Shapeless 对“抽象超过 arity”的支持。
  • 在对 Vector 调用操作之前,将 Vector 转换为相同类型。 Gabriele Petronella 给出了一个很好的例子,它使用标准 Scala 库提供的隐式在 Scala 2.10 或更高版本上执行此操作。

  • 直接使用类型类:

    这种方法在您第一次创建时有点冗长,因为必须为想要支持的每个值组合创建隐式类。但这种方法是合理的。可以阅读有关类型类的更多详细信息 here

    如果要将以下代码复制并粘贴到 scala REPL 中,请务必先输入 ':paste'。否则 trait 和伴生对象之间的关系将不会被拾取,并且在输入 'a+b' 时将找不到隐式。
    trait NumberLike[A,B,C] {
    def plus(x: A, y: B): C
    }
    object NumberLike {
    implicit object NumberLikeIntDouble extends NumberLike[Int,Double,Double] {
    def plus(x: Int, y: Double): Double = x + y
    }
    implicit object NumberLikeDoubleInt extends NumberLike[Double,Int,Double] {
    def plus(x: Double, y: Int): Double = x + y
    }
    implicit object NumberLikeIntInt extends NumberLike[Int,Int,Int] {
    def plus(x: Int, y: Int): Int = x + y
    }
    }


    case class Vector2[T](val x: T, val y: T) {
    def +[B,C](that: Vector2[B])(implicit c:NumberLike[T,B,C]) : Vector2[C] = new Vector2[C](c.plus(this.x,that.x), c.plus(this.y,that.y))
    }

    val a = Vector2(1,2)
    val b = Vector2(2.0,2.0)

    a+a
    a+b
    b+a

    要将更多运算符添加到向量中,例如减法和除法,然后将它们添加到 NumberLike 特征并使用上面的加号示例进行操作。

    关于scala - 在 Scala 中实现通用向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25324429/

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