我试图为Ether编写flatMap的简单实现
sealed trait Either[+L, +R] {
def flatMap[B](f: R => Either[L, B]): Either[L, B] = this match {
case Left(e) => Left(e)
case Right(e) => f(e)
}
}
final case class Right[+A, +B](right: B) extends Either[A, B]
final case class Left[+A, +B](left: A) extends Either[A, B]
并遇到以下问题: 协变类型L在类型f中处于协变位置:R =>值f的[L,B]都可以,为什么呢?我以为当我们将变量类型作为函数的参数时,我们的类型就处于反变的位置,与类型声明无关
答案 0 :(得分:3)
您可以将R => Either[L, B]
视为“类型为L
的通用值”-它与L
并不完全相同,但是给定R
可能会产生一个L
。因此,您的flatMap
“使用类型L
的广义值”。同时,您的差异声明声称Either[+L, +R]
与L
是协变的,因此,Either[VerySpecial, R]
必须是Either[RatherGeneral, R]
的特例。但这是不可能的,因为仅消耗flatMap
值的VerySpecial
会阻塞RatherGeneral
输入。
Either[+L, +R]
中,L
处于协变位置(至少在"produces" L
s个位置中R => Either[L, B]
中,L
仍处于协变位置(因为该函数产生Either[L, B]
,而Either[L, B]
又产生L
,因此整个事物产生L
s)(R => Either[L, B]) => Either[L, B]
中,第一个L
出现在 contra 变体位置,因为自变量部分被方法{{1}消耗了 }。这可以通过标准的lower-type-bounds技巧轻松解决:
flatMap