问题描述
我尝试为任何一个编写 flatMap 的简单实现
I tried to write simple implementation of flatMap for Either
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],但为什么会这样?当我们将变体类型作为函数的参数时,我认为我们的类型处于逆变位置,它与类型声明无关
and faced following problem:covariant type L is in contravariant position in type f: R => Either[L, B] of value f, but why is it so? I thought that our type is in contravariant position when we take variant type as an argument for function and it has nothing to do with a type declaration
推荐答案
你可以想到 R =>[L, B]
作为L
类型的广义值" - 它与 L
不完全相同,但给定了 R
它可能产生一个L
.因此,您的 flatMap
使用 L
类型的广义值".同时,您的方差声明声称 Either[+L, +R]
在 L
中是协变的,因此,Either[VerySpecial, R]
必须是 Either[RatherGeneral, R]
的特例.但这是不可能的,因为只能使用 VerySpecial
值的 flatMap
会阻塞 RatherGeneral
输入.
You can think of R => Either[L, B]
as a "generalized value of type L
" - it's not exactly the same thing as an L
, but given an R
it might produce an L
. So, your flatMap
"consumes generalized values of type L
". At the same time, your variance declaration claims that Either[+L, +R]
is covariant in L
, therefore, an Either[VerySpecial, R]
would have to be a special case of Either[RatherGeneral, R]
. But this is impossible, because the flatMap
that can consume only VerySpecial
values would choke on a RatherGeneral
input.
- 在
Either[+L, +R]
中,L
处于协变位置(它 产生"L
s,在至少有时) - 在
R =>[L, B]
,L
仍然处于协变位置(因为函数产生Either[L, B]
,而Either[L, B]
依次产生L
s,所以整个事情产生L
s) - 在
(R =>Either[L, B]) =>要么[L, B]
,第一个L
出现在contra变体位置,因为参数部分被方法消耗flatMap
.
- In
Either[+L, +R]
,L
is in covariant position (it "produces"L
s, at least sometimes) - In
R => Either[L, B]
,L
is still in covariant position (because the function producesEither[L, B]
, andEither[L, B]
in turn producesL
s, so the whole thing producesL
s) - In
(R => Either[L, B]) => Either[L, B]
, the firstL
appears in contravariant position, because the argument part is consumed by the methodflatMap
.
使用标准的下限技巧很容易解决这个问题:
This is easily fixed with the standard lower-type-bounds trick:
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]
这篇关于L型在A型中处于逆变位置=>要么[L, B]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!