I'm interested if I can create method with similar idea:
def myMethod[T](param: T)(implicit oneOf: Either[TypeClass1[T], TypeClass2[T]]) = oneOf match ...
I've tried to use default parameters (I've seen somethin similar in akka):
def myMethod[T](param: T)(implicit t1: TypeClass1[T] = null, t2: TypeClass2[T] = null) =
if (t1 == null) ...
However, that way I cannot force scala compiler to find at least one of them.
Also, I've implemented implicit conversion from TypeClass1[T] to Left[TypeClass1[T], TypeClass2[T]] and from TC2 to Right, however Scala compiler ignores this conversions.
Is there any way to do something like this?
The obvious solution is to create a new typeclass that can be constructed using either TypeClass1 or TypeClass2. The new typeclass implements the functionality used by myMethod that is common to both and maps it to the appropriate methods on TypeClass1 or TypeClass2.
Here is an example:
trait TypeClass1[T] {
def showOne = println("Typeclass 1")
}
trait TypeClass2[T] {
def showTwo = println("Typeclass 2")
}
trait UnionTypeClass[T] {
def show
}
object UnionTypeClass {
implicit def t1[T](implicit ev: TypeClass1[T]) = new UnionTypeClass[T] {
def show = ev.showOne
}
implicit def t2[T](implicit ev: TypeClass2[T]) = new UnionTypeClass[T] {
def show = ev.showTwo
}
}
implicit object IntClass extends TypeClass1[Int]
implicit object StringClass extends TypeClass2[String]
def myMethod[T](param: T)(implicit ev: UnionTypeClass[T]) = {
ev.show
}
myMethod(0)
myMethod("hello")
This will print
Typeclass 1
Typeclass 2
In Scala 3 you might be able to use union type like so
trait Foo[A]
trait Bar[A]
given foo as Foo[Int] {}
def g[T](using Foo[T] | Bar[T]) = summon
foo[Int] // ok
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With