使用2个参数键入约束

时间:2016-02-05 19:35:20

标签: scala

假设:

scala> sealed trait Parent
defined trait Parent

scala> case object K extends Parent
defined object K

scala> case object J extends Parent
defined object J

scala> sealed trait Result 
defined trait Result

scala> case object KResult extends Result
defined object KResult

scala> case object JResult extends Result
defined object JResult

如何实施以下F

scala> def f[A <: Parent, B <: Result](x: A): B = ???
f: [A <: Parent, B <: Result](x: A)B

我们假设K必须有KResultJJResult

但是,我担心的是在编译时传递f[K, JResult]没有强制约束。

或许,我可以简单地诉诸:

def f(x: Parent): Result = x match {
  case K => KResult
  case J => JResult

但是,这种做法的弱点在于我可能会犯错:

def badF(x: Parent): Result = x match {
  case K => JResult
  case J => KResult

1 个答案:

答案 0 :(得分:1)

您需要一种方法在类型系统中将KResultK相关联。您可以通过向A添加类型参数Result来实现这一目标(可选地,它可以具有Parent的上限,但这可能不是必需的。)

sealed trait Parent

case object K extends Parent

case object J extends Parent

sealed trait Result[A]

case object KResult extends Result[K.type]

case object JResult extends Result[J.type]

然后,B可以被Result[A]限制,这将强制执行以下事实:A = K,然后是B <: Result[K]

def f[A <: Parent, B <: Result[A]](x: A): B = ???

scala> f[K.type, Result[J.type]](K)
<console>:16: error: type arguments [K.type,Result[J.type]] do not conform to method f's type parameter bounds [A <: Parent,B <: Result[A]]
       f[K.type, Result[J.type]](K)
        ^

这种方法虽然没有多大意义,但由于无法推断结果类型,因此必须手动提供。不过,这就是你如何强制执行这些限制。