scalatypeclassdispatch

How do you define a type class for a union of types?


The problem I'm having is that I'm getting infinite recursion when I try to define a type class on a union.

trait Foo[A]:
  extension (a: A)
    def bar: String

Now suppose I have the following givens defined:

given Foo[Int] with ...

given Foo[String] with ...

Now I want to create a union

type Value = String | Int

and, of course, Value should be a member of the type class. But if I do this:

given Foo[Value] with
   extension (v: Value)
     def bar: String = v match
       case i: Int => i.bar
       case s: String => s.bar

the problem is that i.bar and s.bar call the bar that goes with Value, not with Int or String, and I end up with infinite recursion. And casting them doesn't help.

Because bar is an extension function, I'm not sure how to get Foo[Int] and Foo[String] so that I could make the calls directly. Is there a way out of this, or have I coded myself into a corner?


Solution

  • How about this:

    scala> given Foo[Value] with
         |    extension (v: Value)
         |      def bar: String = v match
         |        case i: Int => summon[Foo[Int]].bar(i)
         |        case s: String => summon[Foo[String]].bar(s)
         |
    // defined object given_Foo_Value