Scala中的通用点加法

时间:2018-02-09 07:22:23

标签: scala implicit-conversion

我试图使用加法和加法乘法成员对Tuple(2)类进行皮条客,这样我就可以更容易地将它们用作几何2D点。这就是我所拥有的:

implicit class Point[+T: Numeric](val t: (T, T)) {
  import Numeric.Implicits._
  def _1 = t._1
  def _2 = t._2

  def +[V >: T](p: Point[V])(implicit ev: Numeric[V]) : (V,V) = 
    (ev.plus(t._1, p._1), ev.plus(t._2, p._2))
}

println((2, 3) + Point(5.0, 6.0))

这不起作用(无法找到ev),大概是因为严格来说Float不是Int的超级类型 - 但是没有&#39 ; t实际上似乎是一个弱一致性运算符,完全不让它意味着我不能再使用ev.plus因为它期望两个相同类型的值{{1} },而不是VT之一。

如何正确实现此代码?

2 个答案:

答案 0 :(得分:1)

你是对的。问题是Numeric[T]根据其签名V不允许人们混合使用类型(Tdef plus(x: T, y: T): T)。

您可以使用/模拟此库: https://github.com/azavea/numeric。它做了许多隐含的体操,允许混合类型工作。

它完全符合您的需求:

  

EasyImplicits允许您对混合数字类型(例如T + U + Int)进行操作。

或者选择使用基础Double类型而不是T / V - 我知道这并不总是很好(精度损失等)。

你的代码仍可以使用不混合类型的点,但是Double看起来并不那么糟糕,因为无论如何都会发生自动转换。

答案 1 :(得分:1)

我相信因为构造函数参数是一个元组,所以它应该简单的数字扩展变得复杂。这涵盖了许多(大多数?)转换。

from concurrent.futures import ThreadPoolExecutor

def wait_on_future():
    f = 3
    import time
    time.sleep(19)
    print(f)

with ThreadPoolExecutor(max_workers=2) as executor:      
    executor.submit(wait_on_future)
print("elo")

用法:

implicit class Point[T: Numeric](a: (T, T)) {
  import Numeric.Implicits._
  val _1 = a._1
  val _2 = a._2

  def +(x: T, y: T) = add(_1, _2, x, y)

  def +[U: Numeric](x:U, y:U)(implicit ev: T => U) =
    add[U](ev(_1), ev(_2), x, y)

  def +[U: Numeric](b: Point[U])(implicit ev: T => U) =
    add[U](ev(_1), ev(_2), b._1, b._2)

  private def add[N: Numeric](a:N, b:N, c:N, d:N) = (a+c, b+d)
}

但它不会将作为参数传递的现有(1, 4) + (2.2, 4.4) //res0: (Double, Double) = (3.2,8.4) (2.1, 3.1) + (9, 2) //res1: (Double, Double) = (11.1,5.1) (1, 4) + Point((5.2, 6.2)) //res2: (Double, Double) = (6.2,10.2) Point((2, 3)) + (4L, 5L) //res3: (Long, Long) = (6,8) Point((1.5, 2.9)) + (1, 1) //res4: (Double, Double) = (2.5,3.9) 的元素扩展为Point方法。

+()