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处于反变量位置。
有人可以向我解释为什么会这样吗?感觉一头雾水。
我假设您实际上打算写:
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
处于协变位置。本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句