geoffliu
geoffliu

Reputation: 520

Wrapping overloaded functions in Scala (possibly using macro)

Suppose I have types A, B, and C, and an overloaded method:

def foo(a: A): C
def foo(b: B): C

Then suppose I have a (complicated) piece of code that works with objects of type C. What I would like to have is a method that takes either type A or B:

def bar(x: [A or B]) = {
  val c = foo(x)
  // Code that works with c
}

Of course I could write two versions of bar, overloaded to take types A and B, but in this case, there are multiple functions that behave like bar, and it would be silly to have overloaded versions (in my actual case, there are three versions of foo) for all of them.

C-style macros would be perfect here, so I thought to look into Scala macros. The awkward part is that Scala macros are still typed-checked, so I can't just say

reify(foo(x.splice))

since the compiler wants to know the type of x beforehand. I'm entirely new to using Scala macros (and it's a substantial API), so some pointers in this regard would be appreciated.

Or if there's a way to layout this code without macros, that would be helpful too!

Upvotes: 1

Views: 184

Answers (1)

EECOLOR
EECOLOR

Reputation: 11244

You can solve your problem differently.

Instead of say type A or B think about what you want from those types. In your example it would be enough if you said: "It doesn't matter what type it is, as long as I have a foo method for it". That's what the code below shows:

trait FooMethod[T] {
  def apply(t:T):C
}

object FooMethod {
  implicit val forA = new FooMethod[A] {
    def apply(a:A):C = foo(a)
  }

  implicit val forB = new FooMethod[B] {
    def apply(b:B):C = foo(b)
  }
}

def bar[X](x: X)(implicit foo:FooMethod[X]) = {
  val c = foo(x)
  // Code that works with c
}

Upvotes: 1

Related Questions