scala 中的擦除消除:未选中非变量类型参数,因为它已被擦除消除
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25222989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Erasure elimination in scala : non-variable type argument is unchecked since it is eliminated by erasure
提问by BSJ
I've got a sequence Seq[Any] that has a variety of objects in it (like String, Integer, List[String], etc). I'm trying to sift through the list and break it up into separate lists partitioned based on the class type. The following is a pattern I'm using in the code:
我有一个序列 Seq[Any],其中包含各种对象(如 String、Integer、List[String] 等)。我正在尝试筛选列表并将其分解为基于类类型分区的单独列表。以下是我在代码中使用的模式:
val allApis = mySequence.filter(_.isInstanceOf[String])
This works well and doesn't generate any warnings. However, when I try to do the same for filtering out the objects that are Lists of strings:
这很有效并且不会产生任何警告。但是,当我尝试做同样的事情来过滤掉作为字符串列表的对象时:
val allApis = mySequence.filter(_.isInstanceOf[List[String]])
I get a warning that says non-variable type argument String in type List[String] is unchecked since it is eliminated by erasure. Now, the technique actually works and I'm able to comfortably filter the sequence as desired, but I'm wondering what is the appropriate way to deal with the warning in an idiomatic way so that I know I don't have a serious bug lurking in the background waiting to blow up
我收到一条警告,指出类型 List[String] 中的非变量类型参数 String 未选中,因为它已被erasure 消除。现在,该技术确实有效,我可以根据需要轻松地过滤序列,但我想知道以惯用方式处理警告的适当方法是什么,以便我知道我没有严重的错误潜伏在后台等待炸毁
回答by Rex Kerr
It doesn't work because it will pick out List[Double]or any other list in addition to List[String]. There are a variety of ways of fixing the problem, including wrapping any parameterized types in a non-parameterized case class:
这是行不通的,因为它会挑选出List[Double]或补充任何其他列表List[String]。有多种解决问题的方法,包括将任何参数化类型包装在非参数化案例类中:
case class StringList(value: List[String])
and then you can just
然后你就可以
mySequence.collect{ case StringList(xs) => xs }
to pull out the lists of strings (with the correct type, and type-safely also).
拉出字符串列表(使用正确的类型,并且类型安全)。
Alternatively, if you want to not wrap objects and want to be sure that they're of the correct type, you can check every element:
或者,如果您不想包装对象并希望确保它们的类型正确,您可以检查每个元素:
mySequence.filter( _ match {
case xs: List[_] => xs.forall( _ match { case _: String => true; case _ => false })
case _ => false
})
though even this won't let you know which type empty lists were supposed to be.
尽管即使这样也不会让您知道应该是哪种类型的空列表。
Another possibility is to glue TypeTags to everything in your list; this will prevent you needing to manually wrap things. For instance:
另一种可能性是将TypeTags粘贴到列表中的所有内容;这将防止您需要手动包装东西。例如:
import scala.reflect.runtime.universe.{TypeTag, typeTag}
def add[A](xs: List[(Any, TypeTag[_])], a: A)(implicit tt: TypeTag[A]) = (a, tt) :: xs
val mySequence = add(add(add(Nil, List(42)), true), List("fish"))
mySequence.filter(_._2.tpe weak_<:< typeTag[List[String]].tpe)
回答by Vikas Pandya
val v = 1 ::"abc" :: true :: Nil
v : List[Any] = List(1,abc,true)
type parameter of Listtype has been unified to the greatest common super type of the elements in the Listwhich is Any.
type 的 type 参数List已经统一List为Any.
Shapelessis to the rescue.
无形是拯救。
import shapeless._
import HList._
val s = 1 :: "abc" :: true: HNil
s : shapeless.::[Int,shapeless.::[String,shapelsss.::[Boolean,shapeless.HNil]]]
= 1 :: abc :: true :: HNil
With Shapeless HListyou can get compile time safety for a heterogeneous list. you can now filterin a typesafe manner. e.g.
使用 Shapeless,HList您可以获得异构列表的编译时安全性。您现在可以filter以类型安全的方式。例如
s.filter[String]

