Circe: semi-auto can't derive enc/dec for case classes with fields with tagged types

Created on 3 Apr 2017  路  11Comments  路  Source: circe/circe

Hey folks,

I have a weird interaction between shapeless tagged types and semi automatic derivation for case classes. I created a minimal example which can be found here: http://scastie.org/29940

The values e1 to e3 are only there to show that the buildling blocks for the automatic derivation seem to be in place and should not affect the derivation.

Maybe I'm just doing something wrong with tagged types or circe?

Greetings :)

Most helpful comment

Okay, I've tracked the difference between 2.11 and 2.12 down to a change in the way the RefinedType extractor works. I'll try to get a fix together today.

All 11 comments

I am also facing the same issue, hitting this only when upgraded to 2.12.1, was working fine for scala 2.11.8

@felher This looks similar to https://github.com/circe/circe/issues/220

I have the encoders explicitly defined above the semiauto for the case class using the tagged types and it is not working either. Example below:

type EmailAddress = String @@ EmailAddressTag
type Password = String @@ PasswordTag
final case class CustomerRegistrationEntity(email: EmailAddress, password: Password)

object Encoders {
  implicit val emailEncoder: Encoder[EmailAddress] = Encoder.encodeString.contramap(identity)
  implicit val passwordEncoder: Encoder[Password] = Encoder.encodeString.contramap(identity)

  implicit val encodeCustomerRegistrationEntity: Encoder[CustomerRegistrationEntity] = 
    deriveEncoder(Lazy.mkLazy[DerivedObjectEncoder[CustomerRegistrationEntity]])
}

Still getting an Unable to derive io.circe.generic.encoding.DerivedObjectEncoder[CustomerRegistrationEntity]

@fthomas Yeah, it does. The fix for this one might actually fix #220 too, since it seems to be a problem with circe, refined and type tags, and this is a problem with just circe and type tags :)
@javierarrieta thanks for checking that :+1:

This is stopping me to move to scala 2.12, any ideas for a workaround would be greatly appreciated (manual codec is not a real option for me)

@javierarrieta Does explicitly putting instances into scope for the refined types work? It's annoying but it seems to be fine for me on 2.12:

import eu.timepit.refined.numeric.Positive
import io.circe.Encoder
import io.circe.generic.auto._
import io.circe.refined.refinedEncoder
import shapeless.tag.@@

implicit val positiveIntEncoder: Encoder[Int @@ Positive] = refinedEncoder

case class Foo(i: Int @@ Positive)

Encoder[Foo]

@travisbrown it works when you have a single type-tagged argument but fails when there are more.

Is there any hope this can be fixed in near future? Or there are some compiler limitations/problems?

Okay, I've tracked the difference between 2.11 and 2.12 down to a change in the way the RefinedType extractor works. I'll try to get a fix together today.

Wow, so cool, thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aesteve picture aesteve  路  4Comments

LukaJCB picture LukaJCB  路  7Comments

nathankleyn picture nathankleyn  路  7Comments

allantl picture allantl  路  6Comments

darkfrog26 picture darkfrog26  路  4Comments