Erasure elimination in scala : non-variable type argument is unchecked since it is eliminated by erasure

前端 未结 2 977
予麋鹿
予麋鹿 2020-12-23 15:04

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 separa

相关标签:
2条回答
  • 2020-12-23 15:23
    val v = 1 ::"abc" :: true :: Nil
    v : List[Any] = List(1,abc,true) 
    

    type parameter of List type has been unified to the greatest common super type of the elements in the List which is Any.

    Shapeless is 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 HList you can get compile time safety for a heterogeneous list. you can now filter in a typesafe manner. e.g.

    s.filter[String]
    
    0 讨论(0)
  • 2020-12-23 15:31

    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:

    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:

    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)
    
    0 讨论(0)
提交回复
热议问题