Skip to content

Shortcut to pass-through type-classes for opaque type  #17653

@ivan-klass

Description

@ivan-klass

Opaque types are very helpful to enforce type safety, but in practice it often leads to a silly boilerplate code when defining type-classes for them (e.g. circe codecs, db read/write, config readers, etc) which are nothing but a pass-through to a TC instance for underlying type.

One-for-all tricks like the below may help but don't cover all the cases (some derivations may diverge) and may also silently bring an implementation when pass-through is not desired

  abstract class OpaqueCompanion[O, A](using ev: A =:= O):

    given typeClass[TC[_]](using tc: TC[A]): TC[O] = ev.liftCo(tc)


  opaque type Counter = Int

  object Counter extends OpaqueCompanion[Counter, Int]

Explicitly putting given into a companion disables a way to summon TC for underlying type resulting in infinite loop in function body, e.g:

opaque type Counter = Int
object Counter:
  given Numeric[Counter] = Numeric[Int] // no way, infinite loop in function

It would be much better if there's a way to declare a pass-through type-classes, something like

opaque type Counter = Int derives Numeric

or

opaque type Counter = Int opaque Numeric

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions