Как сопоставить шаблон всем классам с привязкой к контексту - PullRequest
1 голос
/ 18 октября 2019

У меня есть класс типов и несколько экземпляров:

trait TC[T] { def doThings(x: T): Unit }
implicit val tcA = new TC[A] { /* ... */}
implicit val tcB = new TC[B] { /* ... */}
implicit val tcC = new TC[C] { /* ... */}
/* ... */

На моем сайте вызовов у меня есть входные данные как Any, и мне нужно проверить, существует ли неявное для фактического типа ввода:

def process(in: Any) = in match {
  case x: A => implicitly[TC[A]].doThings(x)
  case x: B => implicitly[TC[B]].doThings(x)
  case x: C => implicitly[TC[C]].doThings(x)
  //...
}

Это кажется утомительным и ненужным, так как я должен перечислить все классы, которые имеют этот экземпляр класса типа. Могу ли я достичь этого с помощью чего-то вроде:

def process(in: Any) = in match {
  case x: T : TC => implicitly[TC[T]].doThings(x) //This does not work
}

Редактировать: ввод - Any (Объект из библиотеки Java). Невозможно использовать общий или контекстный ограниченный ввод.

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Если вы действительно хотите сделать то, что упомянули в своем вопросе, вы можете написать это, как показано ниже, но если вы просто хотите позвонить doThings, найдя неявный экземпляр соответствующего TC - см. Ответ João Guitana

object Main extends App {
  class A
  class B
  class C

  trait TC[T] { def doThings(x: T): Unit }
  implicit val tcA = new TC[A] {
    override def doThings(x: A): Unit = println("From A")
  }
  implicit val tcB = new TC[B] {
    override def doThings(x: B): Unit = println("From B")
  }
  implicit val tcC = new TC[C] {
    override def doThings(x: C): Unit = println("From C")
  }

  def process[T: ClassTag](in: T) = in match {
    case x: A => implicitly[TC[A]].doThings(x)
    case x: B => implicitly[TC[B]].doThings(x)
    case x: C => implicitly[TC[C]].doThings(x)
  }

  process(new A())
  process(new B())
  process(new C())

}
/* === Output ====
From A
From B
From C
*/

1 голос
/ 18 октября 2019

Вам нужно попросить неявное TC, Any не будет работать. Как указано ниже:

trait TC[T] { def doThings(x: T): Unit }

implicit def tcS: TC[String] = new TC[String] {
  override def doThings(x: String): Unit = println("string")
}

implicit def tcI: TC[Int] = new TC[Int] {
  override def doThings(x: Int): Unit = println("int")
}

def process[T : TC](x: T): Unit = implicitly[TC[T]].doThings(x)

process("")
process(1)
// process(4L) wont compile

Попробуйте!

...