Typeclass instance that is more specific than typeclass

As an alternative to creating new classes at compile-time, I am attempting to make a macro to produce instances of a typeclass that are more specific than the typeclass, basically adding new methods to it, since Scala 3 does not have macro annotations. To get started, I made this simple example (Scastie):

trait TC[T] extends reflect.Selectable
object TC:
  transparent inline given derived[T]: TC[T] =
    new TC:
      val foo: String = "Hello World!"

class Useless derives TC

@main def main =
  println(compiletime.summonInline[TC[Useless]].foo)

However, I get an error saying foo is not a member of TC[Useless]. That makes sense, but what I don’t get is why it thinks the type of the instance is TC[Useless] and not the more specific TC[Useless] { val foo: String }. I used a transparent given, extended Selectable to allow refinements to be recognized, and used summonInline, which is again transparent.

Is there something I can do to make the last line compile, or is it impossible to derive typeclass instances more specific than declared?

1 Like

The derives thing seems to throw the extra refinement away.

scala> trait TC[T] extends reflect.Selectable
     | object TC:
     |   transparent inline given derived[T]: TC[T] =
     |     new TC:
     |       val foo: String = "Hello World!"
     | 
// defined trait TC
// defined object TC

scala> class Foo
// defined class Foo

scala> class Bar derives TC
// defined class Bar

scala> summon[TC[Foo]]
val res7: TC[Foo]{foo: String} = anon$1@6689f455

scala> summon[TC[Bar]]                                                          
val res8: TC[Bar] = anon$1@47effce0

Might be a bug / feature request.

1 Like