当类型参数出现在不变位置时,如何使特征逆变?

时间:2018-05-29 08:25:02

标签: scala contravariance

我想在其类型参数中使用以下特征逆变。

asm(
        "ldr r0, [r1, %[my_offset]] \n" : : [my_offset]"i" (offsetof(MyStruct, a))
    );

上述解决方案的问题在于Scala标准库trait Preferences[-A] { def ordering: Ordering[A] } 在其类型参数中是不变的。这篇SO帖子讨论了为什么会出现这种情况。

我已经为我的问题开发了两种解决方案。第一种解决方案是使参数Ordering和上限。

A

第二种是使用trait Preferences[-A] { def ordering[B <: A]: Ordering[B] }

implicit

这两个都编译,但我不理解权衡。这些方法中的一种更普遍吗?我应该使用第三种方法吗?

1 个答案:

答案 0 :(得分:3)

在尝试解决您遇到的问题时,您的第一个解决方案被认为是最佳做法(具有逆变参数作为方法或函数的返回类型)。

第二个解决方案称为通用类型约束,当您想要推断出正确的类型而不让编译器“适合它们”时,它们非常有用。例如,如果你有

def foo[A, B <: A](a: A, b: B): Whatever = ???

并且您尝试将其作为

调用
foo(42, "something")

编译器会将A推断为Any,因为这样整个事情就适合了;类型BString,确实是Any的子类型。有了GTC:

def foo[A, B](a: A, b: B)(implicit ev: B <:< A)

编译器会将您的参数分别推断为IntString。只有在那之后它才会检查GTC,并且这里不会进行扩展,因为已经推断出参数类型。因此编译将失败,因为String不是Int。

的子类型

只要你明确定义你的A和B,并且你总是会(因为没有什么可以推断它们),你的第一个解决方案就好了。不需要暗示。