Reputation: 520
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
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