How can I alias a covariant generic type parameter
 
以下代码无法编译(在Scala 2.11中):
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | case class CovariantClass[ +R]( value:  R) {
  type  T =  R
  def  get:  R =  value
}
object  Main {
  def  main( args:  Array[ String]):  Unit ={ 
    println( CovariantClass[ String]("hello") .get)
  }
} | 
错误消息是:
| 12
 3
 
 | Error:(4 , 8)  covariant type  R occurs in invariant position in type  R of type  T
  type  T =  R 
       ^ | 
为什么不能为协变类型参数起别名?如果删除行type T = R,代码将编译并打印hello,因此别名似乎是问题所在。不幸的是,这意味着我无法为更复杂的类型创建别名,例如type T = List[R]也不会编译,尽管List是协变的。 
根据scala规范:
The right-hand side of a type alias is always in invariant position.
这意味着您无法创建别名T并在右侧指定变量类型R。 List[R]也是相同的,因为它也是协变的。
但是,您可以提供带有类型参数的类型别名:
| 12
 3
 4
 
 | case class CovariantClass[ +R]( value:  R) {
  type  T[ +R] =  List[ R]
  def  get:  R =  value
} | 
如果发现自己想为类型参数R加上别名,则应该首先将其命名为其他名称。
		
		
- 感谢您的回答和引用scala规范。我同意重命名R而不是对其进行别名,但是我想为Either[ReturnValueInCaseOfFailure,R]之类的东西取一个别名。不幸的是,您建议的变通方法将T参数化,但是它可能是我所需要的最接近的方法。
 
	 
之所以禁止,是因为它会允许不正确的程序,这始终是规则。您可以这样重写它:
关于如何中断的示例,请考虑以下问题:
| 12
 3
 4
 5
 6
 
 | case class CovariantClass[ +R]( value:  R) {
  type  T =  Int
  def  get:  R =  value
  def  put( x:  T) {}
  def  put2( x:  R) {}
} | 
由于T的定义方式,它是不变的。这意味着它可以在协变量类型不能使用的地方使用,如上所示。请注意put会编译,但put2不会编译。
		
		
- 
有趣的。但是,在此示例中,R应该是T的下限,这样代码才能中断,对吗?另外,我不知道如何在不引入类型绑定的情况下破坏它。这只是保守的设计选择吗?无论如何:谢谢您的示例。
- 
@KuluLimpa我为可能出现的问题添加了一个示例。这只是一个示例的开始,以说明这与差异问题之间的关系。如果您需要更多信息,请查询有关方差的问题-应该有一些示例,说明为什么某些位置的变体类型是非法的(我知道我之前写过:)。