Scala泛型:数字
我有以下Java代码:Scala泛型:数字,scala,generics,implicit,Scala,Generics,Implicit,我有以下Java代码: import java.util.List; import java.util.ArrayList; import java.util.Arrays; public class NumTest { public static void main(String[] args) { final List<Integer> list1 = Arrays.asList(1, 2); final List<Float&g
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class NumTest {
public static void main(String[] args) {
final List<Integer> list1 = Arrays.asList(1, 2);
final List<Float> list2 = Arrays.asList(3.0f, 4.0f);
final List<Double> list3 = Arrays.asList(5.0, 6.0);
assertCloseEnough(list1, Arrays.asList(1.0, 2.0));
assertCloseEnough(list2, Arrays.asList(3.0, 4.0));
assertCloseEnough(list3, Arrays.asList(5.0, 6.0));
}
private static void assertCloseEnough(List<? extends Number> actuals, List<? extends Number> expecteds) {
assert actuals.size() == expecteds.size();
for(int i = 0; i < actuals.size(); i++) {
System.err.println(actuals.get(i).doubleValue());
assert Math.abs(actuals.get(i).doubleValue() - expecteds.get(i).doubleValue()) < 1E-10;
}
}
}
不起作用:
TestNum1.scala:5: error: could not find implicit value for evidence parameter of type Numeric[AnyVal]
assertCloseEnough(Seq(1,2), Seq(1.0, 2.0))
^
TestNum3.scala:5: error: ambiguous implicit values:
both object BigIntIsIntegral in object Numeric of type scala.math.Numeric.BigIntIsIntegral.type
and object IntIsIntegral in object Numeric of type scala.math.Numeric.IntIsIntegral.type
match expected type Numeric[N]
assertCloseEnough(Seq(1,2), Seq(1.0, 2.0))
^
更高级的版本:
import Numeric.Implicits._
object TestNum extends App {
assertCloseEnough(Seq[Int](1,2), Seq[Double](1.0, 2.0))
assertCloseEnough(Seq[Float](3.0f,4.0f), Seq[Double](3.0, 4.0))
assertCloseEnough(Seq[Double](5.0,6.0), Seq[Double](5.0, 6.0))
def assertCloseEnough[N: Numeric](actuals: Seq[N], expecteds: Seq[N]): Unit = {
assert(actuals.size == expecteds.size)
val ad = actuals.map(implicitly[Numeric[N]].toDouble(_))
val ed = expecteds.map(implicitly[Numeric[N]].toDouble(_))
for (i <- expecteds.indices) {
assert(Math.abs(ad(i) - ed(i)) < 1E-10)
}
}
}
我错过了什么?如何才能使其工作?您需要使用两种类型(例如T1
和T2
),并为您的方法提供隐式参数或使用隐式
从隐式范围调用数值
以下是两种方法:
def assertCloseEnough[T1: Numeric, T2: Numeric](actuals: Seq[T1], expecteds: Seq[T2]): Unit = {
assert(actuals.size == expecteds.size)
val ad = actuals.map(implicitly[Numeric[T1]].toDouble)
val ed = expecteds.map(implicitly[Numeric[T2]].toDouble)
for (i <- expecteds.indices) {
assert(Math.abs(ad(i) - ed(i)) < 1E-10)
}
}
def assertCloseEnough[T1, T2](actuals: Seq[T1], expecteds: Seq[T2])(implicit t1: Numeric[T1], t2: Numeric[T2]): Unit = {
assert(actuals.size == expecteds.size)
val ad = actuals.map(_.toDouble)
val ed = expecteds.map(_.toDouble)
for (i <- expecteds.indices) {
assert(Math.abs(ad(i) - ed(i)) < 1E-10)
}
}
def assertcloseough[T1:Numeric,T2:Numeric](实际值:序号[T1],预期值:序号[T2]):单位={
断言(actuals.size==expecteds.size)
val ad=actuals.map(隐式[Numeric[T1]].toDouble)
val ed=expecteds.map(隐式[Numeric[T2]].toDouble)
对于(i您的序列有两种不同类型的元素,但您正试图将其参数化为一种。
像这样的方法应该会奏效:
def assertCloseEnough[N1, N2](expected: Seq[N1], actual: Seq[N2])(implicit e1: Numeric[N1], e2: Numeric[N2]) {
assert(
expected.size == actual.size &&
(expected zip actual).forall { case (a,b) =>
math.abs(e1.toDouble(a)-e2.toDouble(b)) < 1e-10
}
)
}
def assertclosevery[N1,N2](预期值:Seq[N1],实际值:Seq[N2])(隐式e1:Numeric[N1],e2:Numeric[N2]){
断言(
预期的.size==实际的.size&&
(预期为zip实际值)。对于所有{情况(a,b)=>
数学绝对值(e1.双音(a)-e2.双音(b))<1e-10
}
)
}
这个声明相当于非常接近[N1:Numeric,N2:Numeric](…)
,但在本例中它更方便一些,因为它隐式地给出了“证据”的实际名称,所以您不必使用隐式地[Numeric[N1]]
另外,不要将foo(i)
与Seq
一起使用,这几乎总是一个坏主意。
如果您确定需要随机访问(大多数情况下不需要),请使用IndexedSeq
def assertCloseEnough[T1: Numeric, T2: Numeric](actuals: Seq[T1], expecteds: Seq[T2]): Unit = {
assert(actuals.size == expecteds.size)
val ad = actuals.map(implicitly[Numeric[T1]].toDouble)
val ed = expecteds.map(implicitly[Numeric[T2]].toDouble)
for (i <- expecteds.indices) {
assert(Math.abs(ad(i) - ed(i)) < 1E-10)
}
}
def assertCloseEnough[T1, T2](actuals: Seq[T1], expecteds: Seq[T2])(implicit t1: Numeric[T1], t2: Numeric[T2]): Unit = {
assert(actuals.size == expecteds.size)
val ad = actuals.map(_.toDouble)
val ed = expecteds.map(_.toDouble)
for (i <- expecteds.indices) {
assert(Math.abs(ad(i) - ed(i)) < 1E-10)
}
}
def assertCloseEnough[N1, N2](expected: Seq[N1], actual: Seq[N2])(implicit e1: Numeric[N1], e2: Numeric[N2]) {
assert(
expected.size == actual.size &&
(expected zip actual).forall { case (a,b) =>
math.abs(e1.toDouble(a)-e2.toDouble(b)) < 1e-10
}
)
}