Scala: возвращение зависимого типа - PullRequest
2 голосов
/ 28 марта 2019

В моем приложении у меня есть закрытый набор операций, которые возвращают соответствующий набор ответов, как показано ниже.

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)
}

Что касается моего понимания элементов типа и проекции типа, я могу сделать следующее. Это совершенно правильные утверждения в соответствии с компилятором scala

val esr:StartExecutionOperation#R = ExecutionStartedResponse(1)
val teo:TerminateExecutionOperation#R = ExecutionTerminatedResponse(-1)
val ruo:RecordUpdateOperation#R = UpdateRecordedResponse(0)

Однако я бы хотел использовать их в функции; что часто более полезно. Теперь, как бы я указал тип вывода как зависимый тип?

def updateState[O <: Operation](operation: O) = operation match {
    case StartExecutionOperation() =>  ExecutionStartedResponse(1)
    case TerminateExecutionOperation() => ExecutionTerminatedResponse(-1)
    case RecordUpdateOperation() => UpdateRecordedResponse(0)
}

В частности, я не хочу, чтобы тип возвращаемого значения функции в моем случае был OperationCompletionResponse , но что-то вроде Operation # R или operation.R

Как мне это сделать?

1 Ответ

2 голосов
/ 28 марта 2019

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

Вы определили ровно одну операцию, которая дает вам R, и это createResponse. Поскольку createResponse ожидает целочисленный аргумент, вы должны как-то указать его в updateState. Похоже, у вас есть состояние по умолчанию для каждой из операций, поэтому вы можете определить это def defaultState: Int Operation и затем иметь

def updateState(op: Operation): op.R = op.createResponse(op.defaultState)` 

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

...