协变类型 FParam 在值猜测的类型 Seq[FParam] 中以逆变位置出现



考虑这个简单的例子:

trait Optimizer[+FParam, FRes] {
def optimize(
fn: (FParam) => FRes,
guesses: Seq[FParam] // <--- error
)
}

它不编译,因为

协变类型FParam在值猜测的类型Seq[FParam]中以逆变位置出现。

但是seq被定义为trait Seq[+A],那么这种逆变的来源是什么?(问题1(

相反,考虑这个简单的例子,-FParam

trait Optimizer[-FParam, FRes] {
def optimize(
fn: (FParam) => FRes, // <--- error
guesses: Seq[FParam]
)
}
逆变型

(FParam) => FRes型中以协变位置出现

同样,同样的悖论:在Function1[-T1, R]中,第一个类型参数显然是逆变的,那么为什么FParam处于协变位置呢?(问题2(

我可以通过翻转方差来解决此问题,如类型下限中所述,但为什么有必要尚不清楚。

trait Optimizer[+FParam, FRes] {
type U <: FParam
def optimize(
fn: (FParam) => FRes,
guesses: Seq[U]
)
}

问题 1+FParam表示协变类型FParam,它因超型而异FParam。 对于guesses,它期望cotravariant typeSeq。因此,您可以通过为此明确说明supertypeFPParam来做到这一点,例如:

def optimize[B >: FParam](fn: (B) => FRes, guesses: Seq[B]) // B is the super type of FParam

或者像SeqViewLike一样。

那么为什么guesses它期待Seqcotravariant type呢? 例如:

trait Animal
case class Dog() extends Animal
case class Cat() extends Animal
val o = new Optimizer2[Dog, Any]
val f: Dog => Any = (d: Dog) =>  ...
o.optimize(f, List(Dog(), Cat())) // if we don't bind B in `guesses` for supertype of `FParam`, it will fail in compile time, since the `guesses` it's expecting a `Dog` type, not the `Animal` type. when we bind it to the supertype of `Dog`, the compiler will infer it to `Animal` type, so `cotravariant type` for `Animal`, the `Cat` type is also matched.

问题 2-FParam表示cotravairant类型FParam,它因超型FParam子类型而异fn: Function1[-T1, +R]//(FParam) => FRes因此,您可以通过反转问题 1类型状态来做到这一点,例如:

def optimize[B <: FParam](fn: (B) => FRes, guesses: Seq[B]) // B is the sub type of FParam

问题是 FParam 没有直接使用。它在optimize的论证中,因此它的方差被颠倒了。为了说明,让我们看一下optimize的类型(见val optim(:

trait Optimizer[+FParam, FRes] {
type U <: FParam
def optimize(
fn: (FParam) => FRes,
guesses: Seq[U]
)
val optim: Function2[
Function1[
FParam,
FRes
],
Seq[U],
Unit
] = optimize
}

刚刚解决了这个问题,希望我能消除混乱。

Seq[] 不是列表,并且不能同时包含多个类类型。 您的特征优化器有一个未知但固定的类 FParam 或子类,但返回 Seq[FParam] 的函数不一定与封闭对象是同一个子类。因此,最终可能会有一个运行时,不同的子类同时在 Seq[FParam] 中结束,因此整个代码块都变成了 Scala 编译错误。

abstract class Optimizer[+FParam, FRes] {
}
object Optimizer{
def optimize[FParam,FRes](obj: Optimizer[FParam,FRes], param : FParam) : (FParam,Seq[FParam]) = (param,(Nil)) 
}

特征(现在是一个抽象类(仍然具有协变泛型参数,但在其参数中使用该协方差泛型的函数被类型锁定为具有不变的精确类型 - 强制要求函数中的相同类或子类现在在单例对象中。

相关内容

  • 没有找到相关文章

最新更新