Scala Set[_] 与 Set[Any] [英] Scala Set[_] vs Set[Any]

查看:52
本文介绍了Scala Set[_] 与 Set[Any]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码行:

case set: Set[Any] => setFormat[Any].write(set)

然而,编译器发出警告:

However, the compiler issues a warning:

非可变类型参数 Any in type patternscala.collection.Set[Any] 未被选中,因为它被消除了擦除 [警告]

non-variable type argument Any in type pattern scala.collection.Set[Any] is unchecked since it is eliminated by erasure [warn]

很公平.

所以我改成这样:

case set: Set[_] => setFormat[Any].write(set)

现在出现错误:

[错误] 发现:scala.collection.Set[_]

[error] found : scala.collection.Set[_]

[错误] 需要:scala.collection.Set[Any]

[error] required: scala.collection.Set[Any]

第一季度.这两者有什么区别?

然后我将代码更改为以下内容:

Then I change my code to the following:

case set: Set[_] => setFormat[Any].write(set.map(s => s))

现在很满意,没有错误或警告.

Now it is happy with no errors or warnings.

第二季度.为什么这样做?

推荐答案

Q1:Set[Any] 是元素类型为 Any 的 Set.Set[_] 是元素类型未知的 Set.也许它是一个 Set[Int],也许是一个 Set[String],也许是一个 Set[Any].与大多数(不可变)集合相反,Set 不是协变的(声明是 trait Set[A],而不是 trait Set[+A]).所以 Set[String] 不是 Set[Any],更一般地说,你不能保证你不知道元素类型(即 Set[_]) 是一个 Set[Any].

Q1: A Set[Any] is a Set whose elements type is Any. A Set[_] is a Set whose elements type is unknown. Maybe it's a Set[Int], maybe a Set[String], maybe a Set[Any]. Contrary to most (immutable) collections, Set is not covariant (declaration is trait Set[A], not trait Set[+A]). So a Set[String] is not a Set[Any], and more generally, you cannot guarantee that a set whose elements type you do not know (i.e. Set[_]) is a Set[Any].

Q2:它有效,因为无论集合元素的(未知)类型 A 是什么,恒等函数 s =>s 可以被认为是一个函数 A =>任何.(方差是 Function1[-T1, +R].然后,结果 set.map(s => s) 可以输入为 Set[Any],根据需要.

Q2: It works because whatever the (unknown) type A of the elements of set, the identity function s => s can be considered to a a function A => Any. (variance is Function1[-T1, +R]. Then, the resulting set.map(s => s) can be typed as Set[Any], as required.

备注:如果没有 setFormat 和 write 的定义就很难确定,但是您是否真的需要在 中使用 [Any] 类型参数明确表示setFormat[Any]?可以将一个existential 传递给一个泛型函数,即

Remark: Difficult to be sure without the definition of setFormat and write, but do you really need to be explicit with the [Any] type argument in setFormat[Any]? One may pass an existential to a generic function, i.e

val x: X[_] = ....
def f[A](xa: X[A]) = ...
f(x) // allowed

但在调用站点明确(例如 f[Any](x))是不允许的,因为我们不知道 X 是否是 X[Any].

but being explicit at the call site (e.g f[Any](x)) will not be allowed, as we do not know whether X is an X[Any].

注意:关于 Set 不是协变的:这很不幸,因为人们非常觉得一组 Cats 也是一组 Animals.这是一个原因(可能还有其他原因).

Note: about Set not being covariant: This is unfortunate, as one feels very much that a set of Cats is a set of Animals too. Here is one reason for that (there might be others).

Set 有一个方法 def contains(a: A): Boolean 并且这个签名可以防止协方差.其他集合有一个 def contains[A1 >: A](a: A): Boolean,它允许协方差,但实际上等效于 def contains(a: Any): Boolean.

Set has a method def contains(a: A): Boolean and this signature prevents covariance. Other collections have a def contains[A1 >: A](a: A): Boolean, which allows covariance, but which is effectively equivalent to def contains(a: Any): Boolean.

它有效,因为该实现基于方法 equals,该方法随处可用(与 JVM 一起提供)并且采用 Any 类型的参数.使用与列表内容无关的类型的值进行调用很可能是错误的,并且更受约束的签名会更好,但为协方差付出的代价很小.

It works, because the implementation is based on method equals, available everywhere (comes with the JVM) and which takes an argument of type Any. It is quite likely that calling with a value of a type unrelated to the list content is a mistake, and that a more constrained signature would be better, but it is a small price to pay for covariance.

但是这个 contains 的宽松签名限制了实现基于 equals(也可能是 hashCode).它不适用于基于 Ordering 的实现,它不接受无类型参数.禁止这种(非常常见的)集合实现可能会被视为协方差的代价太高.

But this relaxed signature for contains constraints the implementation to be based on equals (and possibly hashCode too). It would not work for an implementation based on Ordering, which would not accept an untyped argument. Forbidding such (very common) set implementations may be seen as too high a price for covariance.

这篇关于Scala Set[_] 与 Set[Any]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆