sealed trait Sum[+A, +B] {
def flatMap[A, C](f: B => Sum[A, C]): Sum[A, C] =
this match {
case Failure(v) => Failure(v)
case Success(v) => f(v)
}
}
是不是说功能参数是反变量的,结果是共变的?为什么编译器说A处于反变量位置?我期待编译器抱怨B处于反变体位置。
有人可以向我解释为什么会这样吗?感到困惑。
答案 0 :(得分:4)
我认为你真的打算写:
sealed trait Sum[+A, +B] {
def flatMap[C](f: B => Sum[A, C]): Sum[A, C] = // No shadowing of A
this match {
case Failure(v) => Failure(v)
case Success(v) => f(v)
}
}
再次查看flatMap
:
def flatMap[C](f: B => Sum[A, C]): Sum[A, C]
让我们重写一下:
def flatMap[C]: (B => Sum[A, C]) => Sum[A, C]
让我们从内到外构建类型。
Sum[A, C]
A
是Sum
的参数,通常是协变位置。
B => Sum[A, C]
Sum[A, C]
是函数的结果,通常是协变位置。这两个结合起来,你仍然处于协变位置A
。
(B => Sum[A, C]) => Sum[A, C]
B => Sum[A, C]
也是函数的参数,因此整个事物处于逆变位置。由于A
之前处于协变位置,因此方差合并且A
现在处于逆变位置。
查看B
:
B => Sum[A, C]
函数的参数,通常是逆变位置。
(B => Sum[A, C]) => Sum[B, C]
整个函数也是另一个函数的参数,因此抵消了逆变,B
处于协变位置。
你也可以画出一个漂亮的比喻。查看协变和逆变类型参数的定义:
trait Co[+A]; trait Con[-A]
他们看起来像正面和负面的数字,只是一点点。现在,请记住你在小学中学到的乘法和符号的规则:
(+) * (+) = (+)
(+) * (-) = (-)
(-) * (+) = (-)
(-) * (-) = (+)
这类似于(如果你斜视一下)
Co[Co[A]]
=> A
处于协变位置Co[Con[A]]
=> A
处于逆境中Con[Co[A]]
=> A
处于逆境中Con[Con[A]]
=> A
处于协变状态。