我试着编写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 => EitherL,B值f,但为什么如此?当我们以变量类型作为函数的参数时,我认为我们的类型处于相反的位置,它与类型声明无关。
发布于 2018-08-27 13:35:54
您可以将R => Either[L, B]看作是“L类型的广义值”--它与L并不完全相同,但如果是R,则可能会生成L。因此,您的flatMap“使用L类型的广义值”。同时,您的方差声明声称Either[+L, +R]在L中是协变的,因此,Either[VerySpecial, R]必须是Either[RatherGeneral, R]的特例。但这是不可能的,因为只能使用VerySpecial值的VerySpecial会阻塞RatherGeneral输入。
Either[+L, +R]中,L处于协变位置(至少有时是"produces" Ls )。R => Either[L, B]中,L仍然处于协变位置(因为函数生成Either[L, B],而Either[L, B]反过来生成L,所以整个事物都生成Ls)。(R => Either[L, B]) => Either[L, B]中,第一个L出现在contra_variant位置,因为参数部分是方法flatMap的_consumed。这很容易用标准的下类型界技巧来修正:
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]https://stackoverflow.com/questions/52040427
复制相似问题