Scala метод, который нуждается в одном из двух неявных параметров - PullRequest
3 голосов
/ 06 апреля 2020

Мне интересно, могу ли я создать метод с похожей идеей:

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]] и из TC2 в Right, однако Scala компилятор игнорирует эти преобразования.

Есть ли способ сделать что-то подобное?

Ответы [ 2 ]

7 голосов
/ 06 апреля 2020

Очевидным решением является создание нового класса типов, который может быть сконструирован с использованием TypeClass1 или TypeClass2. Новый класс типов реализует функциональность, используемую myMethod, которая является общей для обоих, и сопоставляет ее с соответствующими методами в TypeClass1 или TypeClass2.


Вот пример:

  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
4 голосов
/ 06 апреля 2020

В 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
...