Saturday, June 24, 2006

Variance in C# Generics to Follow Scala

This paper by Burak Emir, Andrew J. Kennedy, Claudio Russo, Dachuan Yu, slated for ECOOP 2006, has proposed modeling variance in C# generics in line very much similar to what Scala does. The proposed notation is based on definition-site declarations (as in Scala) and uses +/- to model covariance / contravariance, as also in Scala.

This proposed extension will make the following declarations possible:

// Covariant parameters used as result types
interface IEnumerator<+T> { T Current { get; } }

// Covariant parameters used in covariant result types
interface IEnumerable<+T> { IEnumerator<T> GetEnumerator(); }

// Contravariant parameters used as argument types
interface IComparer<-T> { int Compare(T x, T y); }


Here is the corresponding syntax in Scala using a covariant type parameter:

class Array[+a] {
  def apply(index: int): a
  ...
}


In order to ensure type-safety through static type checking, the new extension to variance annotations in C# allows covariant parameters only in producer positions in signatures and contravariant paramaters only in consumer positions. These restrictions are, however, overcome through the use of type constraints:

class List<+T> {
  ...
  List<U> Append<U>(U other) where T : U { ... }
  List<U> Append<U>(List<U> other) where T : U { ... }
  ...
}


Quite similarly we have the same solution in Scala by using a polymorphic method with a lower type parameter bound:

class Stack[+a] {
  def push[b >: a](x: b): Stack[b]
    = new NonEmptyStack(x, this)
  ...
}


As a sidenote, it may be mentioned that Java Generics addresses the variance problem by employing wildcards and using use-site declarations (as opposed to defintion-site in C# and Scala).

No comments: