I want to do something like this:
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)
}
The decoding throws:
Error:(54, 22) could not find implicit value for parameter d: io.circe.Decoder[T]
.flatMap(_.as[T])
Component
is the Sealed Trait.
Is this not possible with circe?
This works (Component
instead of 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)
}
I don't think the problem is the Decoder
as it works with Components
, here it is anyway:
implicit val decodeEvent: Decoder[Component] =
List[Decoder[Component]](
Decoder[DbConnection].widen,
Decoder[DbLookup].widen
).reduceLeft(_ or _)
As can be seen on the documentation the as
method on the Json class, requires an implicit Decoder[T]
.
Since this decoder was not on the scope of the function, the compiler complied about it:
Error:(54, 22) could not find implicit value for parameter d: io.circe.Decoder[T]
.flatMap(_.as[T])
The simplest solution is to just add this implicit to the method and leave the responsibility of providing it to the caller.
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] = ...