类型约束和关于joinLeft的约束

时间:2013-04-15 10:37:03

标签: scala reification

joinLeft定义为:

abstract class Either[+A, +B]

def joinLeft[A1 >: A, B1 >: B, C](implicit ev: A1 <:< Either[C, B1]):
    Either[C, B1] = this match {
    case Left(a)  => a
    case Right(b) => Right(b)
}
  • 使用已知的AB,我们需要implicit ev: A1 <:< Either[C, B1]
    1. 满足约束A1 >: A, B1 >: B
    2. 通知A1 <: Either[C, B1]

  • 为此,我们需要隐含 conforms[A1]conforms[Either[C, B1]]

如果直到现在我仍然是对的,那么A1B1似乎有很多选择,只要它们超出下限AB。所以我想知道scala如何为我们提供A1Either[C, B1](以及它们是什么),以便我们获得隐式conforms以促进<:<完成其断言工作A1 <: Either[C, B1]

P.S。
我认为这个问题与我的另一个问题“joinLeft [A1 >: A, B1 >: B, C]… why are type constraint A1 >: A and B1>: B necessary?”有些相关。如果有人也可以看一下,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

你是对的,有很多选择。通常,泛型方法的类型推断使用参数来确定泛型参数的值

def myMethod[A](aList:List[A])

但是,这不是使用泛型参数的类型推断的唯一方法。值得注意的是,类型参数可以是:

  • 显式
  • 使用预期结果类型确定

在这种情况下,由于无法从参数确定泛型类型参数(因为没有显式参数),您通常会将方法的结果分配给类型变量,或者在方法的末尾使用它具有显式返回类型。

您可能会问自己A1将如何解决,这是一个非常有趣的问题。实际上,A1不存在于输入类型中,也不存在于输出类型中。有什么用?

答案如下,来自Predef.scala

@implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
  sealed abstract class <:<[-From, +To] extends (From => To) with Serializable

由于<:<方法中的From是逆变的

def joinLeft[B1 >: B, C](implicit ev: A <:< Either[C, B1]):
    Either[C, B1] = this match {
    case Left(a)  => a
    case Right(b) => Right(b)
}

将无法正确处理A上的子类。这就是为什么你需要一个额外的泛型类型参数A1,它由Scala编译器通过使用A1来解析,它给出了具有最高优先级的隐式。