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