为什么数字的行为与有序的不同?

发布于 2024-10-14 11:57:49 字数 1003 浏览 3 评论 0原文

Scala 有许多可以用作类型类的特征,例如 scala.math 包中的 OrderedNumeric

例如,我可以使用 Ordered 编写一个通用方法,如下所示:

def f[T <% Ordered[T]](a: T, b: T) = if (a < b) a else b

我想使用 Numeric 做类似的事情,但这不起作用:

def g[T <% Numeric[T]](a: T, b: T) = a * b

为什么有一个OrderedNumeric 之间存在明显差异吗?

我知道还有其他方法可以做到这一点,以下方法可以工作(使用上下文绑定):

def g[T : Numeric](a: T, b: T) = implicitly[Numeric[T]].times(a, b)

但这看起来比仅仅使用 * 来乘两个数字更复杂。为什么 Numeric 特征不包含 * 等方法,而 Ordered 却包含 < 等方法?

我知道还有 Ordering,您可以按照与 Numeric 相同的方式使用它,另请参阅 这个答案

def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)

Scala has a number of traits that you can use as type classes, for example Ordered and Numeric in the package scala.math.

I can, for example, write a generic method using Ordered like this:

def f[T <% Ordered[T]](a: T, b: T) = if (a < b) a else b

I wanted to do a similar thing with Numeric, but this doesn't work:

def g[T <% Numeric[T]](a: T, b: T) = a * b

Why is there an apparent discrepancy between Ordered and Numeric?

I know there are other ways to do this, the following will work (uses a context bound):

def g[T : Numeric](a: T, b: T) = implicitly[Numeric[T]].times(a, b)

But that looks more complicated than just being able to use * to multiply two numbers. Why does the Numeric trait not include methods like *, while Ordered does include methods like <?

I know there's also Ordering which you can use in the same way as Numeric, see also this answer:

def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)

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

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

发布评论

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

评论(3

这个俗人 2024-10-21 11:57:49

如果您从隐式 Numeric[T] 导入符号运算符,则它们是可用的。

def g[T : Numeric](a: T, b: T) = {
  val num = implicitly[Numeric[T]]
  import num._
  a * b
}

如果您只想使用单个运算符,这显然有点笨拙,但在重要情况下,导入的开销并不是全部伟大的。

为什么在没有显式导入的情况下运算符不可用?默认情况下反对使隐式可见的通常考虑因素适用于此,也许更是如此,因为这些运算符被广泛使用。

The symbolic operators are available if you import them from the implicit Numeric[T]

def g[T : Numeric](a: T, b: T) = {
  val num = implicitly[Numeric[T]]
  import num._
  a * b
}

This is clearly a bit unwieldy if you want to make use of just a single operator, but in non-trivial cases the overhead of the import isn't all that great.

Why are the operators not available without an explicit import? The usual considerations against making implicits visible by default apply here, perhaps more so because these operators are so widely used.

梦毁影碎の 2024-10-21 11:57:49

Ordered 只是一些简单的方法,它们返回 IntBoolean,因此不需要类型欺骗。

另一方面,Numeric 具有根据所使用的具体子类返回不同类型的方法。因此,虽然 Ordered 只是一个标记特征,但 Numeric 是一个功能齐全的类型类。

要恢复运算符,您可以在 lhs 操作数上使用 mkNumericOps(在 Numeric 中定义)。

更新

迈尔斯是完全正确的,mkNumericOps是隐式的,所以只需导入该 Numeric 实例就会给你带来所有的魔力......

Ordered is just a few simple pimped methods that return either Int or Boolean, so no type-trickery is needed.

Numeric, on the other hand, has methods that return different types depending on the exact subclass used. So while Ordered is little more than a marker trait, Numeric is a fully-featured type class.

To get your operators back, you can use mkNumericOps (defined in Numeric) on the lhs operand.

UPDATE

Miles is quite right, mkNumericOps is implicit, so just importing that instance of Numeric will give you back all the magic...

初见 2024-10-21 11:57:49

您可以通过执行以下操作将 Miles 的解决方案减少为仅使用 1 个额外行:

添加从 A : NumericNumeric[A]#Ops 的隐式转换

object Ops {
  implicit def numeric[A : Numeric](a: A) = implicitly[Numeric[A]].mkNumericOps(a)
}

,然后将其纳入范围在您的方法中,

def g[T : Numeric](a: T, b: T) = {
  import Ops.numeric
  a * b
}

请参阅 Scala 票证 3538 了解更多信息。

You can reduce Miles' solution to only use 1 extra line by doing this:

Add an implicit conversion from A : Numeric to Numeric[A]#Ops

object Ops {
  implicit def numeric[A : Numeric](a: A) = implicitly[Numeric[A]].mkNumericOps(a)
}

Then bring this into scope in your method

def g[T : Numeric](a: T, b: T) = {
  import Ops.numeric
  a * b
}

See Scala ticket 3538 for more info.

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