2

Here is an observation I've had from a chapter in Programming Scala.

In Scala, I often see the abstract trait pattern:

trait Abstract {
  type T
  def transform(x: T): T
  val initial: T
  var current: T
}

class Concrete extends Abstract {
  type T = String
  def transform(x: String) = x + x
  val initial = "hi"
  var current = initial
}

Why would I choose the abstract trait pattern over parameterized generics?

trait Abstract[T] {
  def transform(x: T): T
  val initial: T
  var current: T
}

class Concrete extends Abstract[String]{
  def transform(x: String): x + x
  val initial: "hi"
  var current: initial
}
Jordan Parmer
  • 36,042
  • 30
  • 97
  • 119
  • possible duplicate of [Scala: Abstract types vs generics](http://stackoverflow.com/questions/1154571/scala-abstract-types-vs-generics) – Dimitri Dec 18 '14 at 20:43

1 Answers1

3

The two approaches are mostly equivalent. One reason we might prefer a type member is so that methods can be written with dependent types rather than having to be generic:

def doSomethingWith(a: Abstract): a.T = ...

is arguably more readable than

def doSomethingWith[T](a: Abstract[T]): T = ...

at least as the signatures get more complicated (particularly if we're doing type-level programming, using Abstract as a type-level function).

There might be also implications for type inference; I don't know precisely how scala type inference works, but as far as I can tell there's no way to partially specify the types of a function:

def functionWeWantToCall[U, V, W](a: Abstract[U], b: Abstract[V], c: Abstract[W])
functionWeWantToCall[String, _, _](x, y, z) //won't compile

def functionWeWantToCall(a: Abstract, b: Abstract, c: Abstract)
functionWeWantToCall(x: Abstract{type T = String}, y, z) //works

So that's a reason I've sometimes found myself using the type member approach.

Also, of course, some people (e.g. those from an ML background) simply find the type member approach more familiar or readable.

lmm
  • 17,386
  • 3
  • 26
  • 37
  • Yes, type inference in Scala is a weird beast. Sometimes inference using type parameters work better than for type members. In Dotty (the new Scala compiler) the two concepts are unified, so hopefully there will be no differences in type inference there. – Jesper Nordenberg Dec 18 '14 at 16:15
  • Last time I followed that discussion, the fear was that it had been "unified" in favour of the thing that worked less well :/. – lmm Dec 18 '14 at 16:18