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)
}
- 已知
A
和B
,我们需要一个implicit ev: A1 <:< Either[C, B1]
- 满足约束
A1 >: A, B1 >: B
。 - 规范
A1 <: Either[C, B1]
- 满足约束
- 我们需要隐式
conforms[A1]
和conforms[Either[C, B1]]
如果我现在仍然是正确的,对我来说,A1
和B1
似乎有很多选择,只要它们超出了A
和B
的下界。所以我想知道scala如何给我们A1
和Either[C, B1]
(以及它们是什么),以便我们得到隐式conforms
,以促进<:<
完成断言A1 <: Either[C, B1]
的工作。
注:
我认为这个问题有点关系到我的另一个"joinLeft [A1>: A, B1>: B, C]…为什么类型约束A1>: A和B1>: B是必要的?"。如果有人也能看一下,我将不胜感激。
你说得对,有很多选择。一般来说,泛型方法的类型推断使用实参来确定泛型形参
的值。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来解决的,A1给出了最高优先级的隐式。