Scala: «Статические значения» в чертах? - PullRequest
0 голосов
/ 06 мая 2018

Допустим, у меня есть:

trait X {
  val x: String
}

Используя миксин, я могу определить такую ​​черту, как

trait XPrinter {
  self: X =>
  def printX: String = "X is: " + x
}

такой, что значение / объект, реализующий XPrinter, реализует x и предоставляет его методам, таким как printX, доступ к значениям, указанным в X, например, x.

Пока все хорошо.

Я хочу знать, есть ли способ иметь черту в виде:

trait XDependent[T <: X] {
  def printX: String = ???
}

Таким образом, экземпляры XDependent имеют доступ к значению T.x, при этом x считается «статическим значением», склеенным с определением типа.

Теперь я понимаю, почему к T.x нельзя получить доступ в XDependent, поскольку подтип типа X даже не должен реализовывать значение x, а T.x может быть абстрактным.

Я понимаю, что, хотя Scala предлагает зависимые от пути типы, так что абстрактный тип, определенный в X, может использоваться в XDependent, как показано здесь:

trait X {
  type Y //which can be constrained as desired.
}

trait XDependent[T <: X]{
  def foo(v:T#Y)
  def bar: T#Y
}

он не предлагает то же самое со значениями, поскольку в Scala существует четкое разделение между типами и значениями.

Теперь я натолкнулся на идеи зависимых от значения типов и литеральных типов . Я хочу знать, имеет ли идея «статическое значение для типов», как показано выше, много общего с этими понятиями и каковы связи.

Я также хотел бы узнать о различных подходах, применяемых на разных языках, о стирании различий между типами и значениями, о том, насколько они совместимы с системой типов Scala, и каковы сложности с точки зрения интеграции «статических значений» с системой типов. то есть, (могут ли они быть) / (что произойдет, если они) переопределены подтипом и т. д.

1 Ответ

0 голосов
/ 07 мая 2018

Если вы можете ослабить требование, чтобы XDependent было trait, и вместо этого сделать его abstract class, то создается впечатление, что класс типов, который предоставляет единственный нулевой метод x, точно что хочешь:

Вот ваша базовая черта X (без X.x или чего-либо, что не было бы "статичным"):

trait X

Теперь вы можете определить класс типов HasStaticX[T], который гарантирует, что для типа T мы можем дать некоторую строку x:

trait HasStaticX[T] {
  def x: String
}

Тогда вы можете использовать это так:

abstract class XDependent[T <: X : HasStaticX] {
  def printX: String = implicitly[HasStaticX[T]].x
}

То, что делает HasStaticX, по сути, создает частичную функцию времени компиляции, которая может принимать тип T и генерировать строковое значение x, связанное с T. Так что, в некотором смысле, это что-то вроде функции, которая принимает типы и возвращает значения. Если это то, что вам нужно, то для «интеграции статических значений» ничего не нужно делать, это просто работает в текущих неэкспериментальных основных версиях Scala.

«Типы, зависящие от значений», будут в точности наоборот: это будут «функции», присваивающие значения значениям.

...