Question

There's a common Java idiom (seen in Enum for example) to declare a generic type variable that has to match the actual derived type.

class Enum<E extends Enum<E>> {
...
}

or, if needed more generic arguments:

abstract class Foo<T, Actual extends Foo<T, Actual>> {
    //now we can refer to the actual type
    abstract Actual copy();
}
class Concrete<T> extends Foo<T, Concrete<T>> {
    Concrete<T> copy() {...}
}

Things can get very verbose really quickly, so I imagined that Scala might have something nicer than a literal translation of the examples above.

Are there any more elegant ways to achieve this?

Was it helpful?

Solution

An alternative formulation is to use abstract type members:

trait Foo { self => 
  type A <: Foo {type A = self.A}
}

With your example:

trait Foo { self =>
  type T
  type Actual <: Foo {type T = self.T; type Actual = self.Actual}
}

trait Concrete extends Foo { self =>
  type T
  type Actual = Concrete {type T = self.T}
}

While this reformulation isn't really nicer at the trait/class declarations, when using the traits/classes it can be much terser. (And as far as I know, there isn't another way to reformulate recursive types).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top