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?
The path-dependent type of
updateStatewill be directly linked to the type ofoperation. You don't want to matchoperationin the body, because this will never give you the typeRyou're looking for.You defined exactly one operation that gives you this
Rand that'screateResponse. BecausecreateResponseexpects an integer argument, you have to somehow give it inupdateState. It appears you have some default state for each of the operations, so you could define thatdef defaultState: IntOperationand then haveIf this doesn't answer you question, please edit it to be more specific about what exactly you are trying to achieve with this state.