使用数字类型界限的适当方法用于Scala中的类

发布于 2025-01-17 20:11:54 字数 1704 浏览 4 评论 0 原文

一般问题:定义使用类型为数字的通用类的正确方法,理想情况下,不使用Scala 2中的任何隐式

特定示例:考虑围绕整数序列构建的以下玩具类:

class NewList(val values: Seq[Int]) {
    def +(x: Int): NewList = new NewList(values.map(_ + x))
}

val x = new NewList(List(1,2,3))
(x + 5).values  // ---> List(6, 7, 8)

现在假设我们要制作 newList generic,围绕任何数字序列缠绕:

// Would not compile
class NewList[T: Numeric](val values: Seq[T]) {
    def +(x: T): NewList = new NewList(values.map(_ + x))
}

上面的代码不会编译 据我所知,由于某些怪异的类型不匹配

cmd2.sc:2: type mismatch;
 found   : T
 required: String
    def +(x: T): NewList[T] = new NewList(values.map(_ + x))
                                                         ^Compilation Failed

Compilation Failed

,显然,此编译错误无法解析变量 x:t numeric> numeric 类型,因此无法解析 plus 的参数类型。尝试声明+(x:numeric [t])或使用(隐式num:t => numeric [t])在类别定义或方法定义中都不会帮助。

进行类编译和行为预期的唯一方法是使用 plus 的方法> 隐式[numeric [t]]

class NewList[T: Numeric](val values: Seq[T]) {
    def +(x: T): NewList[T] = new NewList(values.map(implicitly[Numeric[T]].plus(_, x)))
}

val x = new NewList(List(1,2,3))
(x + 5).values  // ---> List(6, 7, 8)
  • 为什么不能编译器解析方法加上 t ,即使在类别定义中将其声明为数字
  • 是否有更好的方法来解决此问题,而无需使用丑陋的样板隐式[numeric [t]]。加上
  • 通常,我们可以避免隐式在Scala中处理此类案例吗?

General question: What is the proper way to define a generic class typed with a type which is Numeric, ideally without using any implicit in Scala 2?

Specific example: consider the following toy class which is built around Integer sequence:

class NewList(val values: Seq[Int]) {
    def +(x: Int): NewList = new NewList(values.map(_ + x))
}

val x = new NewList(List(1,2,3))
(x + 5).values  // ---> List(6, 7, 8)

Now suppose we want to make NewList generic, wrapping around any numeric sequence:

// Would not compile
class NewList[T: Numeric](val values: Seq[T]) {
    def +(x: T): NewList = new NewList(values.map(_ + x))
}

The code above would not compile due to some weird type mismatch

cmd2.sc:2: type mismatch;
 found   : T
 required: String
    def +(x: T): NewList[T] = new NewList(values.map(_ + x))
                                                         ^Compilation Failed

Compilation Failed

As far as I understand, this compilation error apparently means, that compiler could not resolve variable x: T to be of a Numeric type, and thus could not resolve type of arguments of plus. Trying to declare +(x: Numeric[T]) or using (implicit num: T => Numeric[T]) either in class definition or method definition would not help.

The only way to make the class compile and behave as expected is to use plus method of implicitly[Numeric[T]]:

class NewList[T: Numeric](val values: Seq[T]) {
    def +(x: T): NewList[T] = new NewList(values.map(implicitly[Numeric[T]].plus(_, x)))
}

val x = new NewList(List(1,2,3))
(x + 5).values  // ---> List(6, 7, 8)
  • Why couldn't compiler resolve method plus for T, even though it is declared as Numeric in the class definition?
  • Is there any better way to solve this issue without use of ugly boilerplate implicitly[Numeric[T]].plus?
  • Could we, in general, avoid implicit's to handle such cases in scala?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

临风闻羌笛 2025-01-24 20:11:54

为什么Compiler不能在类别定义中宣布为数字?

首先,因为 t 不是数字;相反,它具有数字 typeclass 与之关联的实例
其次,即使 t 数字,它也不具有+方法;因为同样,这不是类型的工作方式。
检查以下内容:

有没有更好地解决此问题的方法,而无需使用丑陋的样板。

是的,只需导入扩展方法: import numeric.implicits ._ 在顶级或 class 或方法或方法内。

通常,我们可以避免在Scala中处理此类案例吗?

[t:numeric] 只是的糖语法(隐式ev:numeric [t])所以不,您无法避免隐含

很好,真的。

Why couldn't compiler resolve method plus for T, even though it is declared as Numeric in the class definition?

First, because T IS NOT a Numeric; rather it has an instance of Numeric typeclass associated with it
Second, even if T would be a Numeric, it would not have a + method; because, again, that is not how typeclasses work.
Check this: https://gist.github.com/BalmungSan/c19557030181c0dc36533f3de7d7abf4

Is there any better way to solve this issue without use of ugly boilerplate implicitly[Numeric[T]].plus?

Yes, just import the extension methods: import Numeric.Implicits._ either at the top level or inside the class or the method.

Could we, in general, avoid implicit's to handle such cases in scala?

[T: Numeric] is just sugar syntax for (implicit ev: Numeric[T]) so no, you can't avoid implicits

Which is fine, really.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文