我想做以下事情:
val aoeu = List((0, 1), (0, 1, 2))
List(Tuple2, Tuple3).foreach { snth =>
println(aoeu.filter(_.isInstanceOf[snth]).map(_.asInstanceOf[snth]))
}
这可能吗?
答案 0 :(得分:0)
正如我所提到的,Scala中的类型安全和(相对)容易传入一个类型参数并获取一个值。另一种方式是什么是困难的,而不是编译时类型安全的。对于你现在的问题,答案是......有点。我们可以做的是定义一个类型类来捕获安全转换的想法,为我们感兴趣的类型设置一些实例,然后进行操作。所以这就是我所拥有的:
import scala.util.Try
/**
A typeclass to represent safe casting behaviour.
*/
trait HasInstance[A] { def apply(any: Any): Option[A] }
object HasInstance {
/**
A helper to quickly create a typeclass instance.
*/
private class Impl[A](_apply: Any => Option[A])
extends HasInstance[A] {
override def apply(any: Any): Option[A] = _apply(any)
}
/* Instances for standard types. */
implicit val int: HasInstance[Int] =
new Impl(any => Try(any.asInstanceOf[Int]).toOption)
implicit def tuple2[A, B]: HasInstance[Tuple2[A, B]] =
new Impl(any => Try(any.asInstanceOf[Tuple2[A, B]]).toOption)
implicit def tuple3[A, B, C]: HasInstance[Tuple3[A, B, C]] =
new Impl(any => Try(any.asInstanceOf[Tuple3[A, B, C]]).toOption)
}
object Test {
def test(): Unit = {
val xs = List((0, 1), (0, 1, 2))
// Flatmap will automatically filter out `None` values.
println(xs flatMap implicitly[HasInstance[Tuple2[Int, Int]]].apply)
// ==> List((0, 1))
println(
xs flatMap implicitly[HasInstance[Tuple3[Int, Int, Int]]].apply)
// ==> List((0, 1, 2))
}
}
请注意,我们仍然无法捕获列表中的实例,因为它们的类型会强制Scala向上转换为AnyRef
以将它们存储在一起。如果你想拥有并映射异构列表,那么你就处于无形区域。实际上,您可能仍然是因为您可能希望进行泛型推导以便轻松派生HasInstance
的实例。