I have two similar functions which have different return types:
override def getUsers(uri: Uri): F[Either[CodecException, List[User]]] =
for {
response <- retrieveDataFromClient(uri)
result <- Sync[F].delay(response)
} yield result
override def getAnimals(uri: Uri): F[Either[CodecException, List[Animal]]] =
for {
response <- retrieveDataFromClient(uri)
result <- Sync[F].delay(response)
} yield result
And I have implicit circe
decoders for them:
implicit def decodeUser(response: HttpResponse): Either[CodecException, List[User]] = Decoder[List[User]].decode(response.entity)
implicit def decodeAnimal(response: HttpResponse): Either[CodecException, List[Animal]] = Decoder[List[Animal]].decode(response.entity)
Now I have refactored first two methods into generic one:
override def getData[A](uri: Uri): F[Either[CodecException, List[A]]] =
for {
response <- retrieveDataFromClient(uri)
result <- Sync[F].delay(response)
} yield result
And created generic circe
decoder:
implicit def decodeGeneric[A](response: HttpResponse): Either[CodecException, List[A]] = Decoder[List[A]].decode(response.entity)
But I got compilation error:
Could not find an instance of Decoder for List[A]
implicit def decodeGeneric[A](response: HttpResponse): Either[CodecException, List[A]] = Decoder[List[A]].decode(response.entity)
not enough arguments for method apply: (implicit instance: hammock.Decoder[List[A]])hammock.Decoder[List[A]] in object Decoder.
Unspecified value parameter instance.
implicit def decodeGeneric[A](response: HttpResponse): Either[CodecException, List[A]] = Decoder[List[A]].decode(response.entity)
Method retrieveDataFromClient
return F[HttpResponse]
from http client Hammock
and response is implicit parsed into type User
and Animal
(via above decoders and works fine), but now I want to have it generic to remove boilerplate. Is it possible to refactor this code in this way and create generic decoder?
You can't make a generic decoder for every A
, constrain your A
in your decodeGeneric
method to those that can be decoded. Circe auto should give you a decoder for your User
and Animal
classes.
import io.circe.generic.auto._
implicit def decodeGeneric[A](response: HttpResponse)(implicit decoder: Decoder[A]): Either[CodecException, List[A]] =
Decoder[List[A]].decode(response.entity)
Change the method signature by introducing a context bound
implicit def decodeGeneric[A: Decoder](response: HttpResponse): Either[CodecException, List[A]] = Decoder[List[A]].decode(response.entity)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.