【问题标题】:implicit from context bound on collection type parameter从集合类型参数上绑定的上下文中隐含
【发布时间】:2015-04-30 17:30:29
【问题描述】:

我有一些代码通过使用 spray.json 将案例类的 Stream 转换为 json 表示来流式传输响应。这适用于单个案例类,但我想对其进行泛化。

所以我从这样的案例类开始:

import spray.json._
import spray.json.DefaultJsonProtocol._
case class Item(foo: String, bar: Int)
case class Report(baz: String, stream: Stream[Item])
object Protocol { implicit val ItemFormat = jsonFormat2(Item) }

在我的报告流式传输方法中,我有这样的代码(高度简化):

def streamReport(...) {
    import Protocol._

    val handler: PartialFunction[Try[Any], String] = {
        case Success(Report(_, stream)) =>
            stream.head.toJson.compactPrint
    }
}

我想做的是泛化Report 以支持更多项目:

case class Report[T](baz: String, stream: Stream[T])

但现在,当然,streamReport 方法在 Any 类型的范围内找不到 JsonWriter

如果我添加一个上下文绑定到streamReport 的类型参数,然后直接传入Report,我可以做一些接近我想要的事情:

def jsonStream[T : JsonWriter](report: Report[T]): String = 
    implicitly[JsonWriter[T]].write(report.stream.head).compactPrint

但是,我不知道如何使它与PartialFunction 一起工作。以下内容无法编译(也不完全适合,因为部分函数的签名与上面不同):

def handler[T : JsonWriter](): PartialFunction[T, String] = {
    case Success(Report(_, stream)) =>
        implicitly[JsonWriter[T]].write(report.stream.head).compactPrint
}

我不确定哪里出了问题。它与类型擦除有关,还是与将Try[Any] 作为我的部分函数的参数类型有关?如何获取流的元素类型所需的隐式 JsonWriter?

【问题讨论】:

  • 应该handler 真的是PartialFunction[Try[Report[T]], String] 吗?
  • m-z:也许,虽然我正在尝试使用现有代码来处理使用其他类型的其他内容,但需要使用Any。是否有可能以某种方式在两个不同的PartialFunction 签名之间进行映射?
  • 我不知道你最后一句话是什么意思。但是,如果您尝试匹配不依赖于类型参数T 的其他类型,您可能会遇到类型擦除问题。如果没有更多关于匹配内容的详细信息,很难说。
  • 我试图重构的代码是Actor返回响应的框架的一部分,并且此代码(和其他类似方法)返回一个部分函数,​​用于为那些构建处理程序回应。在这种特殊情况下(对于此处理程序),唯一可能返回的是Report[T],但在更大的范围内,还有其他参与者返回其他内容,因此部分函数签名采用Any
  • 我想问题是,不管偏函数签名是什么,在实际匹配块中,我们知道它有一个Report。即使我们不知道T,我希望我们可以使用implicitly 的技巧来获得JsonWriter,但我们做不到。

标签: scala implicit partialfunction


【解决方案1】:

我的猜测是Any 不是问题,问题在于尝试匹配case Success(Report(_, stream)),在Report 的定义现在是Report[T] 之后。

此外,为了找到正确的隐式转换,编译器需要了解所涉及的类型(在编译时)。尝试使用这样的东西:

def streamReport[T](...) {
    import Protocol._

    val handler: PartialFunction[Try[Any], String] = {
        case Success(Report[T](_, stream)) =>
            stream.head.toJson.compactPrint
    }
}

这样,编译器就会知道匹配的是什么,并且可以推断出正确的类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 2020-11-05
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    相关资源
    最近更新 更多