为什么数字的行为与有序的不同?
Scala 有许多可以用作类型类的特征,例如 scala.math
包中的 Ordered
和 Numeric
。
例如,我可以使用 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
为什么有一个Ordered
和 Numeric
之间存在明显差异吗?
我知道还有其他方法可以做到这一点,以下方法可以工作(使用上下文绑定):
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您从隐式 Numeric[T] 导入符号运算符,则它们是可用的。
如果您只想使用单个运算符,这显然有点笨拙,但在重要情况下,导入的开销并不是全部伟大的。
为什么在没有显式导入的情况下运算符不可用?默认情况下反对使隐式可见的通常考虑因素适用于此,也许更是如此,因为这些运算符被广泛使用。
The symbolic operators are available if you import them from the implicit Numeric[T]
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.
Ordered
只是一些简单的方法,它们返回Int
或Boolean
,因此不需要类型欺骗。另一方面,
Numeric
具有根据所使用的具体子类返回不同类型的方法。因此,虽然Ordered
只是一个标记特征,但Numeric
是一个功能齐全的类型类。要恢复运算符,您可以在 lhs 操作数上使用
mkNumericOps
(在Numeric
中定义)。更新
迈尔斯是完全正确的,
mkNumericOps
是隐式的,所以只需导入该 Numeric 实例就会给你带来所有的魔力......Ordered
is just a few simple pimped methods that return eitherInt
orBoolean
, so no type-trickery is needed.Numeric
, on the other hand, has methods that return different types depending on the exact subclass used. So whileOrdered
is little more than a marker trait,Numeric
is a fully-featured type class.To get your operators back, you can use
mkNumericOps
(defined inNumeric
) 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...您可以通过执行以下操作将 Miles 的解决方案减少为仅使用 1 个额外行:
添加从
A : Numeric
到Numeric[A]#Ops
的隐式转换,然后将其纳入范围在您的方法中,
请参阅 Scala 票证 3538 了解更多信息。
You can reduce Miles' solution to only use 1 extra line by doing this:
Add an implicit conversion from
A : Numeric
toNumeric[A]#Ops
Then bring this into scope in your method
See Scala ticket 3538 for more info.