模式匹配组件';x';被约束为isInstanceOf[List[Any]]——但可以';t治疗';x';就像RHS上的那种
为了熟悉Scala列表,我决定实现模式匹配组件';x';被约束为isInstanceOf[List[Any]]——但可以';t治疗';x';就像RHS上的那种,list,scala,functional-programming,List,Scala,Functional Programming,为了熟悉Scala列表,我决定实现flatten,这将需要一个类似以下的列表:list(list(2,4),22,list(1))到list(2,4,22,1) 当我试图运行下面的代码时 def flatify(xs: List[Any]) : List[Any] = { xs match { case Nil=> { Nil } case x::rest if x.isInstanceOf[List[Any]] => { flat
flatten
,这将需要一个类似以下的列表:list(list(2,4),22,list(1))
到list(2,4,22,1)
当我试图运行下面的代码时
def flatify(xs: List[Any]) : List[Any] = {
xs match {
case Nil=> {
Nil
}
case x::rest if x.isInstanceOf[List[Any]] => {
flatify(x):: flatify(rest) // bad line
}
case x::rest => {
x:: flatify(rest)
}
case _ => {
throw new IllegalStateException("cant match")
}
}
}
var list = List(List(4, 5), 9, 10, List(1, 2))
flatify(list)
编译器抱怨该行注释为“//错误行”,并说:
Error:(84, 17) type mismatch;
found : Any
required: List[Any]
flatify(x):: flatify(rest)
^
这让我觉得很奇怪,因为我的守卫条件很明确
要求x
成为isInstanceOf[List[Any]]
。我明白
Any
是List[Any]
的一个超类,但我认为
一旦编译器到达表达式的右侧
flatify(x) :: flatify(rest)
它可以接受x
是一个列表[任何]
我相信我的实现可能会有其他问题,因为我没有
已经完全调试过了,但在我继续之前,我想尝试
了解Scala编译器在这里的用途。有什么提示或建议吗
非常感谢指针。Scala的类型系统(就像Java的一样)不会更改if中变量的类型,即使if条件是isInstanceOf
。有两种方法可以使代码正常工作:
Java的方法是使用cast告诉Scala,在您使用isInstanceOf
检查x是否确实是一个列表后,可以使用x作为列表
Scala的方法是根本不使用isInstanceOf
,而是在模式中使用x:List[Any]
,这确实使x
List[Any]
成为静态类型,因此x
可以作为列表使用,而无需强制转换不更改if内变量的类型,即使if条件为isInstanceOf
。有两种方法可以使代码正常工作:
Java的方法是使用cast告诉Scala,在您使用isInstanceOf
检查x是否确实是一个列表后,可以使用x作为列表
Scala的方法是根本不使用
isInstanceOf
,而是在模式中使用x:List[Any]
,这确实使x
List[Any]
成为静态类型,因此x
可以作为列表使用,而无需强制转换。您正在匹配List[Any]
,因此当您
case x :: tail if(x.isInstanceOf[List[Any]]) => x ...
^ ^ ^
Any true, but the type of Still Any
x is already determined
x
是Any
和tail
是List[Any]
。如果
条件没有改变x的类型
,即使您可以测试x.isInstanceOf[List[Any]]
,x
仍然是Any
。您需要匹配类型本身
def flatify(xs: List[Any]) : List[Any] = {
xs match {
case Nil => Nil
case (x: List[Any]) :: rest => flatify(x) ::: flatify(rest)
case x :: rest => x :: flatify(rest)
case _ => throw new IllegalStateException("cant match")
}
}
此外,还有另一个bug。假设x
正确匹配为List[Any]
,则以下flatify(x)::flatify(rest)
将List[Any]
放在List[Any]
的开头,因此根本不进行展平。所以我把它改成了:
scala> flatify(List(1,2,3,List(4,5,6), List(7,8,9)))
res1: List[Any] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
您在
列表[Any]
上进行匹配,因此
case x :: tail if(x.isInstanceOf[List[Any]]) => x ...
^ ^ ^
Any true, but the type of Still Any
x is already determined
x
是Any
和tail
是List[Any]
。如果
条件没有改变x的类型
,即使您可以测试x.isInstanceOf[List[Any]]
,x
仍然是Any
。您需要匹配类型本身
def flatify(xs: List[Any]) : List[Any] = {
xs match {
case Nil => Nil
case (x: List[Any]) :: rest => flatify(x) ::: flatify(rest)
case x :: rest => x :: flatify(rest)
case _ => throw new IllegalStateException("cant match")
}
}
此外,还有另一个bug。假设x
正确匹配为List[Any]
,则以下flatify(x)::flatify(rest)
将List[Any]
放在List[Any]
的开头,因此根本不进行展平。所以我把它改成了:
scala> flatify(List(1,2,3,List(4,5,6), List(7,8,9)))
res1: List[Any] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
从您和sepp2k处找到有用的答案。。但既然你甚至用:::修复了我的愚蠢错误,我会接受你的,但要感谢你们两个!从您和sepp2k处找到有用的答案。。但既然你甚至用:::修复了我的愚蠢错误,我会接受你的,但要感谢你们两个!