[英]Scala method that needs either one of two implicit parameters
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):我尝试使用默认参数(我在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.但是,这样我不能强制 scala 编译器至少找到其中一个。
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.此外,我已经实现了从TypeClass1[T]
到Left[TypeClass1[T], TypeClass2[T]]
和从TC2
到Right
的隐式转换,但是 Scala 编译器会忽略此转换。
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
.显而易见的解决方案是创建一个可以使用TypeClass1
或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
.新的 typeclass 实现了myMethod
所使用的功能,这两者都是通用的,并将其映射到TypeClass1
或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 useunion type like so在 Scala 3 中,您可能可以像这样使用联合类型
trait Foo[A]
trait Bar[A]
given foo as Foo[Int] {}
def g[T](using Foo[T] | Bar[T]) = summon
foo[Int] // ok
You can use standard shapeless.OrElse
or implicitbox.Priority
from one of libraries您可以使用库之一中的标准shapeless.OrElse
或implicitbox.Priority
https://github.com/milessabin/shapeless https://github.com/milessabin/shapeless
https://github.com/monix/implicitbox https://github.com/monix/implicitbox
def myMethod[T](param: T)(implicit oneOf: OrElse[TypeClass1[T], TypeClass2[T]]) = ???
// def myMethod[T](param: T)(implicit oneOf: Priority[TypeClass1[T], TypeClass2[T]]) = ???
trait TypeClass1[T]
trait TypeClass2[T]
implicit val tc1: TypeClass1[Int] = ???
implicit val tc2: TypeClass2[String] = ???
myMethod(1) //compiles
myMethod("a") //compiles
Type classes OrElse
, Priority
are similar to UnionTypeClass
from @Tim 's answer but they prioritize t1
, t2
.类型类OrElse
, Priority
类似于UnionTypeClass
答案中的UnionTypeClass ,但它们优先考虑t1
, t2
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.