Scala 类型L在类型A中处于逆变位置=>;[L,B]
我试图为这两种方法编写简单的flatMap实现Scala 类型L在类型A中处于逆变位置=>;[L,B],scala,types,variance,contravariance,Scala,Types,Variance,Contravariance,我试图为这两种方法编写简单的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,
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]之一,但为什么会这样?我认为当我们把变量类型作为函数的参数时,我们的类型处于反变量的位置,它与类型声明无关,你可以把
R=>或者[L,B]
看作是“类型的广义值L
”——它与L
不完全一样,但是给定一个R
,它可能会产生一个L
。因此,您的flatMap
“使用L
类型的广义值”。同时,您的方差声明声明或者[+L,+R]
在L
中是协变的,因此或者[VerySpecial,R]
必须是或者[RatherGeneral,R]
的特例。但这是不可能的,因为只能使用VerySpecial
值的flatMap
会被RatherGeneral
输入阻塞
- 在
,中[+L,+R]
处于协变位置(至少有时是L
s)L
- 在
中,R=>or[L,B]
仍然处于协变位置(因为函数产生L
,而or[L,B]
反过来产生or[L,B]
s,所以整个过程产生L
s)L
- 在
中,第一个(R=>or[L,B])=>or[L,B]
以相反的位置出现,因为参数部分由方法L
使用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]
谢谢,很好的解释!但是为什么R类型在R=>或者[L,B]中没有突出显示,并且在逆变位置有一个错误(f消耗R,而R又被flatMap消耗)@nicksigevsky,因为
(R=>X=>Y
应该被认为是R
类型的广义值R
在中是协变的(R=>X=>Y
@nicksigevsky假设你说“我需要一台打印机P
”。然后我问你:你需要打印机做什么?您回答:“我有一个特殊的软件和一个PDF文件,它告诉我,给定一台打印机,P
,我如何生成一个纸制品a
”(也就是说,您有一个P=>a
)。然后我对你说:“只要去一家影印店,它会拿走你的P=>a
,如果你愿意的话,打印出一张完整的列表[a]
”。也就是说,复印机的类型是(P=>a)=>List[a]
。现在,请注意,您可以得到您想要的(打印工件A
),因为复印机(P=>A)=>List[A]
的行为类似于通用打印机P
。