问题
I am trying to do the following
trait Stateful {
type State
}
case class SystemState(system: Stateful, state: system.State) // does not compile
That is, the type of state
depends on (the value of) system
. That, however, is not supported:
illegal dependent method type: parameter appears in the type of another parameter in the same section or an earlier one
With function arguments, I could split the arguments into two argument lists, which is not possible with a case class constructor:
def f(system: Stateful)(state: system.State): Unit = {} // compiles
The best I can do is:
case class SystemState[S](system: Stateful { type State = S }, state: S) // compiles
but I was thinking that it should be possible without a type parameter, since in dotty, I suppose type parameters are desugared to type members.
My question then is, can this be expressed without type parameters?
In a more general context, I'm exploring to what extent type parameters can be replaced by type members, and when is it a good idea to do so.
回答1:
The multiple parameter list approach for dependent types unfortunately is not supported for constructors, so no, you will have to introduce a type parameter.
You could hide that fact if it becomes bothering, though
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)
来源:https://stackoverflow.com/questions/29043554/case-class-constructor-argument-type-depending-on-the-previous-argument-value