与实施特征上的@匹配模式?

时间:2015-11-28 20:54:00

标签: scala

假设:

sealed trait Request

sealed trait HasProxy extends Request
sealed trait HasFoo extends Request

case object One extends HasProxy with HasFoo
case object Two extends HasFoo
case object Three extends HasProxy with HasFoo
case object Four extends HasFoo
case object Five extends HasProxy 

我定义了一个接受HasFoo类型的函数。

def f(x: HasFoo) = ???

最后,我尝试编写一个函数,给定RequestHasFoo个案例的模式匹配,即OneTwo,{{1} }和Three

Four

然而,上述失败。

他们每个人都有scala> def foo(request: Request) = request match { | case xxx @ (One | Two | Three | Four ) => f(xxx) | } <console>:23: error: type mismatch; found : Request required: HasFoo case xxx @ (One | Two | Three | Four ) => f(xxx) ^ 个共同点,但我不确定这是如何适用于模式匹配的。

HasFoo

而不是为scala> import scala.reflect.runtime.universe._ import scala.reflect.runtime.universe._ scala> lub ( List( typeOf[One.type], typeOf[Two.type], | typeOf[Three.type], typeOf[Four.type] ) | ) res2: reflect.runtime.universe.Type = HasFoo with Serializable with Product

的每个模式匹配调用f(_)
One ... Four

检查运行时类型,即scala> def foo(request: Request) = request match { | case One => ??? | case Two => ??? | ... | case _ => ??? | } foo: (request: Request)Nothing

case xxx : One | Two | Three | Four

我有更好的选择吗?

2 个答案:

答案 0 :(得分:4)

这可能是编译器类型推断中的一个错误或至少是一个不受欢迎的限制,但一般来说,如果编译器无法理解某些东西的实际类型是什么 - 在这里你可以确定 - 你可以只是到正确的类型:

case xxx @ (One | Two | Three | Four ) => f(xxx.asInstanceOf[HasFoo])

是的,如果它在将来被修改,它就会变得不优雅并且可能不安全,但你可以通过评论几乎完全解决这个问题。

如果您希望编译器确保强制转换,那么模式匹配并使用guard子句拒绝任何不符合您要求的内容,例如:

case xxx: HasFoo 
     if (xxx match { case One | Two | Three | Four => true
                     case _ => false
     }) => f(xxx)

答案 1 :(得分:1)

如果你想匹配HasFoo的任何内容,那么显而易见:

def foo(request: Request) = request match {
  case xxx: HasFoo => f(xxx)
  case _ => ???
}

由于OneTwoThreeFour都延伸HasFoo,所以第一种情况将匹配所有四种类型;但不是Five