Is it possible to abstract over a typeclass with another typeclass?

I am wondering if it is possible to define a typeclass that is itself parameterized with another typeclass.

I am attempting to define a set of data types that extend AnyVal and for this reason am attempting to avoid any form of trait mixin or inheritance. I have chosen to use typeclasses to get over this apparent limitation.
Suppose I have defined the following data types:

case class uint8 (private val value: Int) extends AnyVal

Now I have thought that it would be a good idea to abstract over the idea of having a single value, so for example suppose I have the following typeclass:

trait Value[A]:
    extension (integer: A)
      def value: Int

which is subsequently extended via:

given Value[uint8] with
      extension(u8: uint8)
        def value: Int = u8._value

Now I am stuck. I wish to implement a higher-order type(class?) which I can use to operate over the Value[A] type defined earlier. I have attempted something such as:

trait Equality[A, B]:
    extension (a: A)
      def == (b: B): Boolean

extended via:

given Equality[Value[_], Value[_]] with
    extension (v1: Value[_])
      def == (v2: Value[_]): Boolean =
        v1.value == v2.value

However, this will not compile on the following:

val a = uint8(10)
val b = uint8(10)
a == b

Claiming:

value is is not a member of uint8 
  a == b

I understand that the use of the value function is not defined for the uint8 type, however; I do not understand why the compiler rejects this formulation. My intuition suggested that because uint8 extends the Value type class that by defining an Equality typeclass over the Value typeclass, Equality would be understood to define value for uint8 from the Value typeclass.

How can I resolve this. Ideally, I assumed the resolution would involve higher-order types as attempted, however; if need be, which steps back do I need to take?

uint8 is NOT a Value that is one of the main points of typeclasses, they don’t form subtyping relationships.

Rather, you want this:

given equalityForValues[A](using Value[A]): Equality[A, A] with
  extension (v1: A)
      def == (v2: A): Boolean =
        v1.value == v2.value

PS: You should prefer opaque type over AnyVal

2 Likes