Scala中的泛型点加法
我试图用加法和scala乘法成员来填充Tuple(2)类,这样我就可以更容易地将它们用作几何二维点。这就是我得到的:Scala中的泛型点加法,scala,implicit-conversion,Scala,Implicit Conversion,我试图用加法和scala乘法成员来填充Tuple(2)类,这样我就可以更容易地将它们用作几何二维点。这就是我得到的: 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.pl
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
的超类型-但实际上似乎没有弱一致性约束运算符,完全忽略它意味着我不能再使用ev.plus
,因为它需要两个相同类型的值V
,而不是t
和V
中的一个
我怎样才能正确地实现这段代码?你完全正确。问题是,
Numeric[T]
不允许根据签名将类型(V
和T
)混合在一起:def plus(x:T,y:T):T
您可以使用/模拟此库:
. 它做了很多隐含的体操,让混合类型的工作
它正是您所需要的:
EasyImplicits允许您对混合数字类型(例如T+U+Int)进行操作
或者选择使用底层的Double
类型而不是T
/V
-我知道这并不总是很好(精度损失等)
您的代码仍然可以使用不混合类型的点,这并不是很糟糕,否则,
Double
看起来并不可怕,因为自动转换无论如何都会发生。我相信,由于构造函数参数是一个元组,它会使本应简单的数字加宽变得复杂。这包括许多(大多数?)转换
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)
但是它不会扩展作为参数传递给+()
方法的现有点的元素
(3.3, 4.5) + Point((1, 3)) //Error:No implicit view available from Double => Int.