Тип аргумента конструктора класса case в зависимости от предыдущего значения аргумента

Я пытаюсь сделать следующее

trait Stateful {
  type State
}

case class SystemState(system: Stateful, state: system.State) // does not compile

То есть тип state зависит от (значения) system. Это, однако, не поддерживается:

незаконно зависимый тип метода: параметр появляется в типе другого параметра в том же разделе или более раннем

С аргументами функции я мог бы разделить аргументы на два списка аргументов, что невозможно с конструктором класса case:

def f(system: Stateful)(state: system.State): Unit = {} // compiles

Лучшее, что я могу сделать, это:

case class SystemState[S](system: Stateful { type State = S }, state: S) // compiles

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

Мой вопрос тогда, может быть выражен без параметров типа?

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

Ответ 1

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

Вы можете скрыть этот факт, если он беспокоится, хотя

trait Stateful {
  type State
}

object SystemState {
  def apply(system: Stateful)(state: system.State): SystemState = 
    new Impl[system.State](system, state)

  private case class Impl[S](val system: Stateful { type State = S }, 
                             val state: S)
    extends SystemState {
    override def productPrefix = "SystemState"
  }
}
trait SystemState {
  val system: Stateful
  val state: system.State
}

case object Test extends Stateful { type State = Int }
val x = SystemState(Test)(1234)