scala type-erasure

Eliminación de borrado en Scala: el argumento de tipo no variable no se selecciona porque se elimina por borrado



type-erasure (2)

Tengo una secuencia Seq [Cualquiera] que tiene una variedad de objetos (como Cadena, Entero, Lista [Cadena], etc.). Estoy intentando examinar la lista y dividirla en listas separadas, divididas según el tipo de clase. El siguiente es un patrón que estoy usando en el código:

val allApis = mySequence.filter(_.isInstanceOf[String])

Esto funciona bien y no genera ninguna advertencia. Sin embargo, cuando trato de hacer lo mismo para filtrar los objetos que son Listas de cadenas:

val allApis = mySequence.filter(_.isInstanceOf[List[String]])

Aparece una advertencia que dice que el argumento de tipo no variable String in type List [String] está desmarcado porque se elimina por borrado . Ahora, la técnica realmente funciona y puedo filtrar cómodamente la secuencia como lo desee, pero me pregunto cuál es la forma adecuada de lidiar con la advertencia de una manera idiomática para que yo sepa que no tengo un error grave. acechando en el fondo esperando explotar


No funciona porque seleccionará List[Double] o cualquier otra lista además de List[String] . Hay una variedad de formas de solucionar el problema, incluido el ajuste de cualquier tipo parametrizado en una clase de caso no parametrizada:

case class StringList(value: List[String])

y luego puedes simplemente

mySequence.collect{ case StringList(xs) => xs }

para sacar las listas de cadenas (con el tipo correcto, y tipo de seguridad también).

Alternativamente, si no desea envolver los objetos y desea asegurarse de que son del tipo correcto, puede verificar cada elemento:

mySequence.filter( _ match { case xs: List[_] => xs.forall( _ match { case _: String => true; case _ => false }) case _ => false })

aunque incluso esto no le permitirá saber qué tipo de listas vacías se supone que debe ser.

Otra posibilidad es pegar TypeTag s a todo lo que esté en su lista; esto evitará que necesites ajustar cosas manualmente. Por ejemplo:

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)


val v = 1 ::"abc" :: true :: Nil v : List[Any] = List(1,abc,true)

El parámetro de tipo de tipo de List se ha unificado con el tipo súper común más grande de los elementos en la List que es Any .

Shapeless es para el rescate.

import shapeless._ import HList._ val s = 1 :: "abc" :: true: HNil s : shapeless.::[Int,shapeless.::[String,shapelsss.::[Boolean,shapeless.HNil]]] = 1 :: abc :: true :: HNil

Con Shapeless HList puede obtener seguridad en tiempo de compilación para una lista heterogénea. ahora puede filter de manera segura. p.ej

s.filter[String]