Получите конкретную реализацию параметризованного признака из параметризованной функции

Попытка получить параметризованную функцию, которая вернула бы указанный сопродукт признака.

sealed trait Tr { def x: Int }
case class Cl1(x: Int) extends Tr
case class Cl2(x: Int) extends Tr

def getTr[A <: Tr](i: Int): A = {
  ???
}

Как этого добиться в Scala 2.11?

1 ответ

Решение

Вы можете использовать TypeTag для A и сравните это с Cl1 а также Cl2:

import scala.reflect.runtime.universe._

def getTr[A <: Tr : TypeTag](i: Int): Tr =
  if (typeOf[A] <:< typeOf[Cl1]) Cl1(i)
  else if (typeOf[A] <:< typeOf[Cl2]) Cl2(i)
  else ??? // etc

getTr[Cl1](42) // Cl1(42)
getTr[Cl2](42) // Cl2(42)

Обратите внимание, что мне пришлось изменить тип возвращаемого значения на Tr. Не может работать сA потому что компилятор не разрешил бы иметь ветки, которые разрешаются в разные типы для A (мы не знаем настоящего A, но это точно не может быть одновременно Cl1 а также Cl2в то же время). Боковое примечание: GADT на самом деле имеют немного специальной обработки компилятором, которая допускает такие случаи, например:

object Test {
  def eval[T](e: Expr[T]): T = e match {
    case IntExpr(i) => i  // is T Int?
    case BoolExpr(b) => b // ...or is it Boolean?
  }
}

Кстати, ваш вопрос - надуманный пример или реальный сценарий? Если это последнее, я считаю, что можно было бы реализовать его более элегантным способом.

Другие вопросы по тегам