需要两个隐式参数之一的Scala方法

brccelvz  于 2022-11-29  发布在  Scala
关注(0)|答案(3)|浏览(125)

我很感兴趣,如果我可以创建方法与类似的想法:

def myMethod[T](param: T)(implicit oneOf: Either[TypeClass1[T], TypeClass2[T]]) = oneOf match ...

我试过使用默认参数(我在akka中看到过类似的东西):

def myMethod[T](param: T)(implicit t1: TypeClass1[T] = null, t2: TypeClass2[T] = null) = 
  if (t1 == null) ...

然而,这样我就不能强迫scala编译器至少找到其中的一个。
此外,我还实现了从TypeClass1[T]Left[TypeClass1[T], TypeClass2[T]]以及从TC2Right的隐式转换,但是Scala编译器忽略了这些转换。
有没有办法做到这一点?

kfgdxczn

kfgdxczn1#

显而易见的解决方案是创建一个可以使用TypeClass1TypeClass2构造的新类型类。新类型类实现了myMethod使用的功能,该功能对两者是通用的,并将其Map到TypeClass1TypeClass2上的适当方法。
以下是一个示例:

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")

这将打印

Typeclass 1
Typeclass 2
4dbbbstv

4dbbbstv2#

在Scala 3中,您可以像这样使用union type

trait Foo[A]
trait Bar[A]

given foo as Foo[Int] {}

def g[T](using Foo[T] | Bar[T]) = summon
foo[Int] // ok
332nm8kg

332nm8kg3#

您可以使用其中一个库中的标准shapeless.OrElseimplicitbox.Priorityimplicitlogic.Or
https://github.com/milessabin/shapeless
https://github.com/monix/implicitbox
https://github.com/Jasper-M/implicitlogic

def myMethod[T](param: T)(implicit oneOf: OrElse[TypeClass1[T], TypeClass2[T]]) = ???
// def myMethod[T](param: T)(implicit oneOf: Priority[TypeClass1[T], TypeClass2[T]]) = ???
// def myMethod[T](param: T)(implicit oneOf: Or[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

类型类OrElsePriority类似于**@Tim**的答案中的UnionTypeClass,但它们优先考虑t1t2

相关问题