类型 L 在类型 A 中处于逆变位置 => Either[L, B]
Type L is in contravariant position in type A => Either[L, B]
我尝试为 Either
编写简单的 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 => Either[L, B] of value f,但为什么会这样呢?当我们将变体类型作为函数的参数时,我认为我们的类型处于逆变位置,它与类型声明无关
您可以将 R => Either[L, B]
视为 "generalized value of type L
" - 它与 L
并不完全相同,但给定 R
它可能 生产一个L
。所以,你的 flatMap
"consumes generalized values of type L
"。同时,您的方差声明声称 Either[+L, +R]
在 L
中是协变的,因此,Either[VerySpecial, R]
必须是 Either[RatherGeneral, R]
的特例。但这是不可能的,因为只能消耗 VerySpecial
值的 flatMap
会在 RatherGeneral
输入时阻塞。
- 在
Either[+L, +R]
中,L
处于协变位置(它 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变体位置,因为参数部分是consumed 通过方法 flatMap
.
这很容易用标准的下限类型技巧解决:
sealed trait Either[+L, +R] {
def flatMap[B, M >: L](f: R => Either[M, B]): Either[M, 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]
我尝试为 Either
编写简单的 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 => Either[L, B] of value f,但为什么会这样呢?当我们将变体类型作为函数的参数时,我认为我们的类型处于逆变位置,它与类型声明无关
您可以将 R => Either[L, B]
视为 "generalized value of type L
" - 它与 L
并不完全相同,但给定 R
它可能 生产一个L
。所以,你的 flatMap
"consumes generalized values of type L
"。同时,您的方差声明声称 Either[+L, +R]
在 L
中是协变的,因此,Either[VerySpecial, R]
必须是 Either[RatherGeneral, R]
的特例。但这是不可能的,因为只能消耗 VerySpecial
值的 flatMap
会在 RatherGeneral
输入时阻塞。
- 在
Either[+L, +R]
中,L
处于协变位置(它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变体位置,因为参数部分是consumed 通过方法flatMap
.
这很容易用标准的下限类型技巧解决:
sealed trait Either[+L, +R] {
def flatMap[B, M >: L](f: R => Either[M, B]): Either[M, 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]