Reputation: 1551
In my application, I have a closed set of operations that return a corresponding set responses as shown below.
sealed trait OperationCompletionResponse {
val state: Int
}
case class ExecutionStartedResponse(state: Int) extends OperationCompletionResponse
case class UpdateRecordedResponse(state: Int) extends OperationCompletionResponse
case class ExecutionTerminatedResponse(state: Int) extends OperationCompletionResponse
sealed trait Operation {
type R
def createResponse(state: Int): R
}
case class StartExecutionOperation() extends Operation {
type R = ExecutionStartedResponse
override def createResponse(state: Int): ExecutionStartedResponse = ExecutionStartedResponse(state)
}
case class RecordUpdateOperation() extends Operation {
type R = UpdateRecordedResponse
override def createResponse(state: Int): UpdateRecordedResponse = UpdateRecordedResponse(state)
}
case class TerminateExecutionOperation() extends Operation {
type R = ExecutionTerminatedResponse
override def createResponse(state: Int): ExecutionTerminatedResponse = ExecutionTerminatedResponse(state)
}
As far as my understanding of type members and type projection go, I can do the following. They're perfectly valid statements according to scala compiler
val esr:StartExecutionOperation#R = ExecutionStartedResponse(1)
val teo:TerminateExecutionOperation#R = ExecutionTerminatedResponse(-1)
val ruo:RecordUpdateOperation#R = UpdateRecordedResponse(0)
However, I would now like to use them in a function; which is often more useful. Now, how would I specify the output type as a dependent type?
def updateState[O <: Operation](operation: O) = operation match {
case StartExecutionOperation() => ExecutionStartedResponse(1)
case TerminateExecutionOperation() => ExecutionTerminatedResponse(-1)
case RecordUpdateOperation() => UpdateRecordedResponse(0)
}
More specifically, I do not want the return type of the function in my case to be OperationCompletionResponse but something like Operation#R or operation.R
How can I accomplish that?
Upvotes: 2
Views: 180
Reputation: 4585
The path-dependent type of updateState
will be directly linked to the type of operation
. You don't want to match operation
in the body, because this will never give you the type R
you're looking for.
You defined exactly one operation that gives you this R
and that's createResponse
. Because createResponse
expects an integer argument, you have to somehow give it in updateState
. It appears you have some default state for each of the operations, so you could define that def defaultState: Int
Operation
and then have
def updateState(op: Operation): op.R = op.createResponse(op.defaultState)`
If this doesn't answer you question, please edit it to be more specific about what exactly you are trying to achieve with this state.
Upvotes: 2