Зависимые типы, не работающие для конструкторов?

Полезны типы, зависящие от пути:

trait Sys {
  type Global
}
def foo[S <: Sys](system: S)(global: system.Global) = ()

Почему это не работает для конструкторов?

class Foo[S <: Sys](val system: S)(val global: system.Global)

Или я просто делаю это неправильно?

Ответы

Ответ 1

Это кажется ошибкой для меня. Изменить: это SI-5712.

В разделе 5.3 раздела 2.9 SLS говорится:

(ps1)., (psn) являются формальными параметрами параметра параметра для основного конструктора класса. Объем формального параметра значения включает все последующие секции параметров и шаблон t.

Есть исключение:

Однако формальный параметр значения не могут быть частью типов любого из родительских классов или членов шаблон класса t.

Но он говорит, что он не может быть частью типов любого из родительских классов или членов, а не из любого из следующих разделов параметров, поэтому он не запрещает типы, зависящие от пути, между группами аргументов.

Вы можете обойти это со вспомогательным конструктором:

class Foo[S <: Sys] private[this] () {
  def this(system: S)(global: system.Global) = this
}

Изменить: этот обходной путь вторичного конструктора не очень хорош: выставлять system или global очень сложно, потому что только первичный конструктор может объявить val s.

Пример с приложением:

class Foo[S <: Sys] private[this] () {
  private[this] var _system: S = _
  private[this] var _global: system.Global = _

  def this(system0: S)(global0: system0.Global) = {
    this
    _system = system0
    _global = global0.asInstanceOf[system.Global]
  }

  lazy val global: system.Global = _global
  lazy val system: S = _system
}

Но это ужасно. Предложение @senia намного лучше.