Имеет ли Scala лучший способ выражения "саморекурсивных общих типов"?
Существует общая идиома Java (например, в Enum
), чтобы объявить типичную переменную типа, которая должна соответствовать фактическому производному типу.
class Enum<E extends Enum<E>> {
...
}
или, если необходимо, более общие аргументы:
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() {...}
}
Вещи могут быть очень подробными очень быстро, поэтому я представил себе, что Scala может иметь что-то приятнее, чем буквальный перевод приведенных выше примеров.
Есть ли еще более элегантные способы достижения этого?
Ответы
Ответ 1
Альтернативная формулировка заключается в использовании элементов абстрактного типа:
trait Foo { self =>
type A <: Foo {type A = self.A}
}
В вашем примере:
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}
}
В то время как эта переформулировка не очень приятна в объявлениях признака/класса, при использовании признаков/классов это может быть много. (И, насколько я знаю, нет другого способа переформулировать рекурсивные типы).