gpt4 book ai didi

Scala 泛型 : Numeric

转载 作者:行者123 更新时间:2023-12-02 20:11:04 24 4
gpt4 key购买 nike

我有以下 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 Generics and Numeric Implicits我想出了以下内容:

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))
^

我在这里缺少什么?我怎样才能让它发挥作用?

最佳答案

您的序列具有两种不同类型的元素,但您试图将其参数化为一种。像这样的东西应该有效:

 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
}
)
}

此声明相当于 closeEnough[N1 : Numeric, N2 : Numeric]( ...) 但在这种情况下更方便一些,因为它为“证据”提供了实际名称"隐式,这样您就不必使用隐式[Numeric[N1]] 来找出它们 ...

另外,不要将 foo(i)Seq 一起使用,这几乎总是一个坏主意。如果您确定需要随机访问(大多数时候不需要),请改用 IndexedSeq

关于Scala 泛型 : Numeric,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53634691/

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