【问题标题】:Circe: Generic Function that returns a specific object of a Sealed Trait (ADT)Circe:返回密封特征 (ADT) 的特定对象的通用函数
【发布时间】:2020-03-30 16:16:14
【问题描述】:

我想做这样的事情:

  def loadYaml[T <: Component](ref: LocalRef): Task[T] = {
    val yamlString = Source.fromResource(ref.url).mkString
    val json: Either[ParsingFailure, Json] = parser.parse(yamlString)
    val component = json.flatMap(_.as[T]) // this line creates the error
    Task.fromEither(component)
  }

解码抛出:

Error:(54, 22) could not find implicit value for parameter d: io.circe.Decoder[T]
        .flatMap(_.as[T])

Component 是密封特征。

circe不可能做到这一点吗?

这有效(Component 而不是T):

  def loadYaml(ref: LocalRef): Task[Component] = {
    val yamlString = Source.fromResource(ref.url).mkString
    val json: Either[ParsingFailure, Json] = parser.parse(yamlString)
    val component = json.flatMap(_.as[Component]) // this line creates the error
    Task.fromEither(component)
  }

我认为问题不在于Decoder,因为它适用于Components,无论如何:

  implicit val decodeEvent: Decoder[Component] =
    List[Decoder[Component]](
      Decoder[DbConnection].widen,
      Decoder[DbLookup].widen
    ).reduceLeft(_ or _)

【问题讨论】:

  • @LuisMiguelMejíaSuárez 我认为问题不在于解码器,因为它与组件一起使用。确保我将其添加到我的问题中。
  • @LuisMiguelMejíaSuárez 谢谢,这行得通!如果您有解释,请将其添加为答案。

标签: scala generics circe


【解决方案1】:

documentation 可以看出,Json 类的as 方法需要implicit Decoder[T]
由于此解码器不在函数范围内,因此编译器对其进行了编译:

错误:(54, 22) 找不到参数 d 的隐式值:io.circe.Decoder[T]
.flatMap(_.as[T])

最简单的解决方案是将 this 隐式添加到方法中,并将提供它的责任留给调用者。

def loadYaml[T <: Component](ref: LocalRef)(implicit ev: Decoder[T]): Task[T] = ...

// Or even shorter (and clearer IMHO) using a context bound.
loadYaml[T <: Component : Decoder](ref: LocalRef): Task[T] = ...

【讨论】:

    猜你喜欢
    • 2015-05-26
    • 1970-01-01
    • 2020-03-23
    • 2016-07-18
    • 2020-04-27
    • 1970-01-01
    • 2022-07-21
    • 2018-10-31
    • 2020-09-10
    相关资源
    最近更新 更多