У меня есть следующий код 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> 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;
}
}
}
Это работает, как и ожидалось, как вы можете проверить с помощью javac NumTest.java && java NumTest
.
Мой вопрос: как мне написать эквивалент вScala?
Самый простой подход:
import Numeric.Implicits._
object TestNum extends App {
assertCloseEnough(Seq(1,2), Seq(1.0, 2.0))
assertCloseEnough(Seq(3.0f,4.0f), Seq(3.0, 4.0))
assertCloseEnough(Seq(5.0,6.0), Seq(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)
}
}
}
Не работает:
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))
^
Чуть более продвинутая версия:
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)
}
}
}
Также не работает, с той же ошибкой.
Глядя на другие вопросы здесь, такие как Универсальные Scala и Числовые последствия Я пришел к следующему:
import Numeric.Implicits._
object TestNum extends App {
assertCloseEnough(Seq(1,2), Seq(1.0, 2.0))
assertCloseEnough(Seq(3.0f,4.0f), Seq(3.0, 4.0))
assertCloseEnough(Seq(5.0,6.0), Seq(5.0, 6.0))
def assertCloseEnough[N: Numeric, T1 <% N, T2 <% N](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)
}
}
}
Что тоже не работает:
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))
^
Что мне здесь не хватает?Как я могу заставить это работать?