Search code examples
scalatypeclassscala-macrosshapelesstype-level-computation

What is the best way to avoid clashing between two typeclass definitions in shapeless


Shapeless has a neat type class derivation mechanism that allows you to define typeclasses and get automatic derivation for any typeclass.

To use the derivation mechanism as a user of a typeclass, you would use the following syntax

import MyTypeClass.auto._

which as far as I understand it is equivalent to

import MyTypeClass.auto.derive

An issue arises when you try and use multiple typeclasses like such within the same scope. It would appear that the Scala compiler only considers the last definition of derive even though there are two versions of the function "overloaded" on their implicit arguments.

There are a couple ways I can think of to fix this. Instead of listing them here, I will mark them as answers that you can vote on to confirm sanity as well as propose any better solution.


Solution

  • I raised this question back in April and proposed two solutions: defining the method yourself (as you suggest):

    object AutoCodecJson {
      implicit def deriveEnc[T] = macro deriveProductInstance[EncodeJson, T]
      implicit def deriveDec[T] = macro deriveProductInstance[DecodeJson, T]
    }
    

    Or using aliasing imports:

    import AutoEncodeJson.auto.{ derive => deriveEnc }
    import AutoDecodeJson.auto.{ derive => deriveDec }
    

    I'd strongly suggest going with aliasing imports—Miles himself said "hadn't anticipated that macro being reused that way: not sure I approve" about the deriveProductInstance approach.