Scala匿名函数genric方差问题

时间:2013-09-08 02:41:43

标签: scala generics contravariance invariants covariant

我正在学习Scala,我很难理解矛盾,协变,不变性等。从Why doesn't the example compile, aka how does (co-, contra-, and in-) variance work?我已经学会了如何将函数视为另一个函数的子类型。 (真的很有用!)

以下代码是我认为解决我的难题的重要部分。我提取的部分我认为会给问题增加不必要的复杂性。根据示例,我有一个Student对象,它将充当生成函数的工厂。

函数将接受AnyVal(Int,Double,Long等)的类型或子类,并且返回输出将具有相同的输入类型。为了实现这一点,学生类接收一个通用(A),它是AnyVal的子类型。抽象类就在那里,所以我可以通过像List [Master [AnyVal]](Student.func1)这样的东西来引用这些学生的列表。

问题是我不能拥有“val函数:List [A] => A”这一行,因为我得到错误“covariant类型A出现在type =>中的逆变位置List [A] => A价值功能“。我不知道为什么返回类型必须是A的逆变量。我可以在某种程度上接受基于Function1特征的名称。

那么我如何在抽象的Master类中定义我的函数,以便返回类型是A类型的逆变?我找到了一个如何使用函数定义来定义它的示例(例如def函数[B>:A](v:B):List [B]),但是如何使用匿名函数实现它?请记住,主抽象类中的“A”必须是协变的,因为会有一个函数列表,它接受所有AnyVal类型(Int,Double等)

真的很感激帮助!如果我的任何术语都没有,请告诉我。 - Scala Learner

abstract class Master[+A] {
    val function: List[A] => A
}

class Student[A <: AnyVal](val function: List[A] => A) extends Master[A]

object Student {
def func1 =
    new Student((params: List[Int])=>params(0) + params(1))
}

val myFunc = Student.func1
val someList = List[Master[AnyVal]](myFunc)

1 个答案:

答案 0 :(得分:0)

创建用协变类型参数化的泛型类或特征非常困难。添加方差注释后,不能将该类型用作任何类方法的参数。这是因为函数的参数是反变量的,并且它们的返回类型是协变的。在this接受的答案中有一个非常好的解释。

如果你真的希望类型是协变的,你必须编写所有方法来获取类型[B&gt;:A]的参数 - 也就是说,将A的超类型作为它们的参数类型。这可能非常具有挑战性;在线Scala文档中可能需要example个杂技。