Я пытаюсь динамически фильтровать (или собирать) список по типу:
Если я делаю это явно, указав тип, он отлично работает
scala> var aList = List("one", 2, 3.3)
aList: List[Any] = List(one, 2, 3.3)
scala> aList.collect{case x:Int => x}
res10: List[Int] = List(2)
Если я хочу написать метод, который делает это в общем, то он не делает:
scala> def collectType[T](l:List[Any]):List[T] = l.collect{case x:T => x}
warning: there were unchecked warnings; re-run with -unchecked for details
collectType: [T](l: List[Any])List[T]
scala> collectType[Int](aList)
res11: List[Int] = List(one, 2, 3.3)
scala> collectType[Double](aList)
res16: List[Double] = List(one, 2, 3.3)
scala> collectType[String](aList)
res14: List[String] = List(one, 2, 3.3)
Сначала я подумал, что он называет тип Integer вместо того, чтобы использовать Integer в качестве типа, но, похоже, это не так:
collectType[Int](aList).foreach(x => println(x))
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
Это как бы откладывает проверку типа, пока не будет принудительно
Что мне не хватает в типах?
Есть ли способ достичь того, чего я хочу достичь?
После прочтения связанных вопросов я пришел к этому. Довольно просто теперь, когда на это было указано. Taggable - это черта, которая знает, как хранить карту тегов для класса
def matches[F <: Taggable](thing:Taggable)(implicit m:Manifest[F]):Boolean = {
thing match {
case e if (m >:> singleType(e)) => true
case x => false
}
}
def findByType[G <: Taggable](list:List[Taggable])(implicit m:Manifest[G]) = {
list.collect{case x if (matches[G](x)) => x}
}