Scala 忽略泛型类型

Scala ignore generic type

我试图避免在 Request 上使用包含可选泛型 Body 的泛型,以避免仅在编写正文时才需要时在任何地方传递泛型,也因为未定义主体时没有类型:

case class Body[A](content: A)(implicit val bodyWritable: BodyWritable[A])

case class Request(url: String, body: Option[Body[_]])
  
private def executeRequest(request: Request) = {    
    val wsClient: StandaloneWSClient = ???
    val requestWithUrl = wsClient.url(request.url)
    request.body.fold(requestWithUrl)(body => requestWithUrl.withBody(body.content)(body.bodyWritable))
}

编译失败:

Error:(20, 90) type mismatch;

found : play.api.libs.ws.BodyWritable[(some other)_(in value body)]

required: play.api.libs.ws.BodyWritable[_(in value body)]

我想知道是否有办法不输入请求。

我正在使用 "com.typesafe.play" %% "play-ws-standalone" % "2.0.4"

总之你不能这样做。当涉及通配符时,表达式的类型参数总是与其他类型参数不同,即使它们来自同一个变量。类型 A body.contentbody.bodyWritable 的类型参数 A 被解析为不同的本地匿名类型,即使它们来自同一个变量 body,但 Scala 不知道这一点,因为它们是单独的表达式。

要解决此问题,最类型安全的方法(也是推荐的方法)是将类型参数添加到 Request 和 executeRequest 以确保类型被解析为相同。

您还可以创建一个采用类型参数的本地方法,以确保两个表达式共享相同的泛型类型:

private def executeRequest(request: Request) = {    
    val wsClient: StandaloneWSClient = ???
    val requestWithUrl = wsClient.url(request.url)
    def f[A](body: Body[A]) = requestWithUrl.withBody(body.content)(body.bodyWritable)
    request.body.fold(requestWithUrl)(body => f(body)) // or shorten to request.body.fold(requestWithUrl)(f)
}

或者,我有时会将调用站点移到声明类型参数的class 中,保证类型参数相同。类似于:

case class Body[A](content: A)(implicit val bodyWritable: BodyWritable[A]) {
  def getRequest(req: WSRequest) = req.withBody(content)
}

case class Request(url: String, body: Option[Body[_]])

private def executeRequest(request: Request) = {    
    val wsClient: StandaloneWSClient = ???
    val requestWithUrl = wsClient.url(request.url)
    request.body.fold(requestWithUrl)(body => body.getRequest(requestWithUrl))
}