This is a repost from scala-debate, since I was told that there's interest from Scalaz people.
Please discuss this on scala-debate if possible to avoid having two discussions on the same topic.
There is demand, it would seem, from myself and from others for supporting named type arguments and default values for type parameters. I was asked by Chris Vogt (my GSOC mentor) whether I would be willing to look at implementing these features, and I said I would.
I plan to write a SIP that specifies how these should work, should an agreement on the issue be reached here.
My current idea for basic naming support is something like this for naming would look something like:
"""
class A[T, U]
val a1 = new A[Int, String] // Call normally
val a2 = new A[T = Int, U = String] // Provide names to make meaning clear
val a3 = new A[U = String, T = Int] // Reverse names, still works
val a4 = new A[Int, U = String] // Provide as many position-resolved arguments as desired before providing name-resolved arguments
"""
My current idea for basic default support would look like:
"""
class B[T = String]
val b1 = new A[String] // Explicitly provide the default type
val b2 = new A[Int] // Provide a different type
val b3 = new A // Infers B[String] instead of B[Nothing]
"""
Of course, they should be able to interact, since they have synergistic benefits:
"""
class C[T = String, U = Int]
val c1 = new String[U = Char, T = Char] // Can use the names
val c4 = new String[String, U = Int] // Still uses positional resolution until named arguments start
val c5 = new String[U = Char] // Default: T = String
val c6 = new String[Char] // Default: U = Int
"""
It should also be possible to use default parameter values with type bounds, variance annotations, etc.:
"""
class D[T = List[_] <: Traversable[_]]
val d1 = new D[Seq[_]] // Works because Seq[_] <: Traversable[_]
val d2 = new D // T defaults to List[_]
val d3 = new D[Int] // Error
class E[+T = Traversable[_]]
val e1 = new T // T defaults to Traversable[_]
val e2: E[Traversable] = new E[List] // Variance
val e3: E[Any] = new E // Right side T defaults to Traversable[_], but it doesn't matter, since it's cast to Any
"""
Note that even though all the examples so far have been with classes, methods should also work.
What I would most appreciate is help in identifying important nonobvious cases and deciding what to do in them.
One that I know about:
"""
def mimic[T = Any](x: T): T = x
mimic("abc") // What's mimic's return type?
"""
It is not entirely clear what we should do here. Normally (without a specified default value), we would infer that T is String in this case. However, it is not clear whether this should take precedence over the default value. I currently think that the default values should have the lowest-possible precedence, as this seems to be the idea that has been used with default parameter values for regular method parameters. In short, I think we should go ahead and infer String in this case. However, I'm not particularly attached to the idea of it working in this way if there is some good reason that it would be less surprising to have more complicated precedence rules.