即使在使用 isInstanceOf 检查类型后 Scala 类型不匹配错误

Eli*_*a R 2 types scala list typechecking

我有一个函数unlist 将任何类型的列表作为第一个参数:

def unlist(xs: List[Any], ys: List[Any]): List[Any] = ...

我在外部列表的第一个元素上调用这个函数,它可能是也可能不是列表。因此,我首先需要检查这个 head 元素本身是否是一个列表,在这种情况下我可以调用我的unlist 函数。我用InsintanceOf方法来做,就像这样:

...
if (xs.head.isInstanceOf[List[Any]]) unlist(xs.head, ys)
Run Code Online (Sandbox Code Playgroud)

但是,由于 xs.head 上的类型不匹配,这不会编译:

Error: type mismatch;
found   : Any
required: List[Any]
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?


PS:由于你们中的许多人建议避免使用类型Any,我必须指出这是编码练习的一部分,旨在使功能尽可能通用

Mar*_*lic 5

为了说明 Mateusz 的评论

isInstanceOf 不被记住

这意味着我们将不得不asInstanceOf像这样跟进

if (list.head.isInstanceOf[List[_]]) unlist(list.head.asInstanceOf[List[_]])
Run Code Online (Sandbox Code Playgroud)

正如 Tim 所演示的那样,模式匹配隐式地执行isInstanceOf/asInstanceOf组合。还可以考虑相关答案

如果您无法重构 out Any,这是最弱的类型,也许尝试尽早恢复尽可能多的类型信息,也许像这样

val lists: List[List[_]] = list.collect { case xs: List[_] => xs }
val ints: List[Int] = list.collect { case i: Int => i }
val strings: List[String] = list.collect { case s: String => s }
Run Code Online (Sandbox Code Playgroud)

请注意,由于类型擦除,我们不能轻易做得比 好得多List[List[_]],例如,以下断言通过

val list: List[Any] = List(List("woo", "hoo"), 42, "kerfuffle")
assert(list.head.isInstanceOf[List[Double]])
Run Code Online (Sandbox Code Playgroud)

在最后一种情况下,编译器警告会告诉您type argument Double in type List[Double] (the underlying of List[Double]) is unchecked since it is eliminated by erasure. 忽略此类警告通常不是一个好主意。