我的问题的背景与论坛中的其他问题相似,但是我找不到完全匹配的内容,查看这些答案后,对我来说仍然是个谜。因此,如果有人可以提供帮助,我深表感谢。我的问题的上下文是使用模式匹配来匹配单例类对象。
例如,如果我要实现自己的列表结构,例如
// An implementation of list
trait AList[+T] // covariant
case class Cons[+T](val head: T, val tail: AList[T]) extends AList[T]
case object Empty extends AList[Nothing] // singleton object
// an instance of implemented list
val xs = Cons(1, Cons(2, Cons(3, Empty)))
// pattern matching in a method - IT WORKS!
def foo[T](xs: AList[T]) = xs match {
case Empty => "empty"
case Cons(x, xss) => s"[$x...]"
}
println(foo(xs)) // => [1...]
// pattern matching outside - IT RAISES ERROR:
// pattern type is incompatible with expected type;
// found : Empty.type
// required: Cons[Nothing]
val r: String = xs match {
case Empty => "EMPTY"
case Cons(x, xss) => s"[$x...]"
}
println(r) // does NOT compile
对我来说,它们看起来像是对相同“对象”的相同“匹配”,一个为什么起作用而另一个失败了?我猜该错误与匹配expr in和out方法的不同有关,但是编译器给出的消息极具误导性。这是否意味着在外部“匹配”时需要像xs.asInstanceOf [AList [Int]]一样显式转换xs?
编译器告诉您,类型xs
为Cons
,不能为Empty
,因此您的第一个case
没有意义。
尝试这个:
val r: String = (xs: AList[Int]) match {
case Empty => "EMPTY"
case Cons(x, xss) => s"[$x...]"
}
或这个:
val ys: AList[Int] = xs
val r: String = ys match {
case Empty => "EMPTY"
case Cons(x, xss) => s"[$x...]"
}
在这种情况下,编译器不知道那case Empty
是没有意义的。
这正是您正在使用的def foo[T](xs: AList[T]) = ...
。使用会出现相同的编译错误def foo[T](xs: Cons[T]) = ...
。
在此特定示例中,有效且详尽的匹配如下所示:
val r: String = xs match {
// case Empty => "EMPTY" // would never happened.
case Cons(x, xss) => s"[$x...]"
}
另外:你应该使自己的AList
特征sealed
:
sealed trait AList[+T]
它允许编译器在不完全匹配时向您发出警告:
val r: String = (xs: AList[Int]) match {
case Cons(x, xss) => s"[$x...]"
}
<console>:25: warning: match may not be exhaustive.
It would fail on the following input: Empty
val r: String = (xs: AList[Int]) match {
^
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句