鉴于:
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) = ???
最后,我尝试编写一个函数,给定 Request
,将在 HasFoo
情况下进行模式匹配,即 One
, Two
, 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
而不是为 One ... Four
的每个模式匹配调用 f(_)
scala> def foo(request: Request) = request match {
| case One => ???
| case Two => ???
| ...
| case _ => ???
| }
foo: (request: Request)Nothing
or 检查运行时类型,即 case xxx : One | Two | Three | Four
:
scala> def foo(request: Request) = request match {
| case (_: One.type | _: Two.type | _: Three.type | _: Four.type ) => ???
| }
我有更好的选择吗?
2 回答
这可能是编译器类型推断中的一个错误或至少是一个不受欢迎的限制,但一般来说,如果编译器无法理解某些东西的实际类型是什么 - 而且在这里你可以确定 - 你可以直接转换为正确的类型:
是的,如果它在将来被修改,它不够优雅且可能不安全,但你几乎可以通过评论完全解决这个问题 .
如果你希望编译器确保强制转换,那么模式匹配并使用一个guard子句来拒绝任何你想要的东西,例如:
如果你想匹配
HasFoo
的任何东西,那么显而易见:由于
One
,Two
,Three
和Four
都扩展HasFoo
,因此第一种情况将匹配所有四种类型;但不是Five
.