簡體   English   中英

Scala 中特征的依賴類型約束(?)

[英]Dependent type constraints (?) on trait in Scala

我有以下 model:

sealed trait MyRequest {
  type Response <: MyResponse
}

sealed trait MyResponse {
  type Request <: MyRequest
}

case class SayHelloRequest(name: String) extends MyRequest {
  override type Response = SayHelloResponse
}

case class SayHelloResponse(greeting: String) extends MyResponse {
  override type Request= SayHelloRequest
}

...

有什么方法可以在類型級別強制請求/響應對匹配在一起嗎? 因此,如果SayHelloRequest的響應類型為SayHelloResponse ,則SayHelloResponse的請求類型必須為SayHelloRequest

就像是:

MyRequest#Response#Request =:= MyRequest

MyResponse#Request#Response =:= MyResponse

嘗試 F 邊界

sealed trait MyRequest { self =>
  type This >: self.type <: MyRequest { type This = self.This }
  type Response <: MyResponse { type Request = self.This }
}

sealed trait MyResponse { self =>
  type This >: self.type <: MyResponse { type This = self.This }
  type Request <: MyRequest { type Response = self.This }
}

case class SayHelloRequest(name: String) extends MyRequest {
  override type This = SayHelloRequest
  override type Response = SayHelloResponse
}

case class SayHelloResponse(greeting: String) extends MyResponse {
  override type This = SayHelloResponse
  override type Request = SayHelloRequest
}
implicitly[SayHelloRequest#Response#Request =:= SayHelloRequest]   // compiles
implicitly[SayHelloResponse#Request#Response =:= SayHelloResponse] // compiles
implicitly[MyRequest#Response#Request <:< MyRequest#This]          // compiles
implicitly[MyResponse#Request#Response <:< MyResponse#This]        // compiles

或類型 class(和 F 邊界)

// type class
trait RequestResponse {
  type Request <: MyRequest[Request]
  type Response <: MyResponse[Response]
}
object RequestResponse {
  type Req[Rq <: MyRequest[Rq]] = RequestResponse { type Request = Rq }
  type Resp[Rsp <: MyResponse[Rsp]] = RequestResponse { type Response = Rsp }
  type Aux[Rq <: MyRequest[Rq], Rsp <: MyResponse[Rsp]] =
    RequestResponse { type Request = Rq; type Response = Rsp }
  // materializers
  def req[Rq <: MyRequest[Rq]](implicit
    reqResp: RequestResponse.Req[Rq]
  ): RequestResponse.Aux[Rq, reqResp.Response] = reqResp
  def resp[Rsp <: MyResponse[Rsp]](implicit
    reqResp: RequestResponse.Resp[Rsp]
  ): RequestResponse.Aux[reqResp.Request, Rsp] = reqResp
}

sealed abstract class MyRequest[This <: MyRequest[This]](
  implicit val reqResp: RequestResponse.Req[This]
) { self: This =>
  type Response = reqResp.Response
}

sealed abstract class MyResponse[This <: MyResponse[This]](
  implicit val reqResp: RequestResponse.Resp[This]
) { self: This =>
  type Request = reqResp.Request
}

case class SayHelloRequest(name: String) extends MyRequest[SayHelloRequest]

case class SayHelloResponse(greeting: String) extends MyResponse[SayHelloResponse]

implicit val sayHelloRequestResponse: RequestResponse.Aux[SayHelloRequest, SayHelloResponse] = null
val rr = RequestResponse.req[SayHelloRequest]
implicitly[rr.Response =:= SayHelloResponse] // compiles
val rr1 = RequestResponse.resp[SayHelloResponse]
implicitly[rr1.Request =:= SayHelloRequest]  // compiles

https://tpolecat.github.io/2015/04/29/f-bounds.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM