繁体   English   中英

toSet和类型推断

[英]toSet and type inference

有人可以解释以下原因为何不起作用。 当我执行toSet ,某种程度上失去了类型推断的编译信息,但是我不明白为什么。

scala> case class Foo(id: Int, name: String)
defined class Foo

scala> val ids = List(1,2,3)
ids: List[Int] = List(1, 2, 3)

scala> ids.toSet.map(Foo(_, "bar"))
<console>:11: error: missing parameter type for expanded function ((x$1) => Foo(x$1, "bar"))
              ids.toSet.map(Foo(_, "bar"))
                                ^

scala> ids.map(Foo(_, "bar")).toSet
res1: scala.collection.immutable.Set[Foo] = Set(Foo(1,bar), Foo(2,bar), Foo(3,bar))

假设我有以下内容:

trait Pet {
  def name: String
}

case class Dog(name: String) extends Pet

val someDogs: List[Dog] = List(Dog("Fido"), Dog("Rover"), Dog("Sam"))

Set的type参数不是协变的,而List是。 这意味着如果我有一个List[Dog]我也有一个List[Pet] ,但是Set[Dog] 不是 Set[Pet] 为了方便起见,Scala允许您在从List (或其他集合类型)到Set的转换过程中向上转换,方法是在toSet上提供显式类型参数。 当您编写val a = ids.toSet; a.map(...) val a = ids.toSet; a.map(...) ,推断出此类型参数,就可以了。 另一方面,当您编写ids.toSet.map(...) ,它不会被推断出来,而且您很不走运。

这样可以进行以下工作:

scala> val twoPetSet: Set[Pet] = someDogs.toSet.take(2)
twoPetSet: Set[Pet] = Set(Dog(Fido), Dog(Rover))

虽然这不是:

scala> val allDogSet: Set[Dog] = someDogs.toSet
allDogSet: Set[Dog] = Set(Dog(Fido), Dog(Rover), Dog(Sam))

scala> val twoPetSet: Set[Pet] = allDogSet.take(2)
<console>:14: error: type mismatch;
 found   : scala.collection.immutable.Set[Dog]
 required: Set[Pet]
Note: Dog <: Pet, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Pet`. (SLS 3.2.10)
       val twoPetSet: Set[Pet] = allDogSet.take(2)
                                               ^

这值得困惑吗? 我不知道。 但这是有道理的,这是Collections API设计师为toSet做出的toSet ,因此我们坚持使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM