从参数化函数中获取参数化特征的特定实现

时间:2019-11-12 21:43:20

标签: scala functional-programming traits case-class coproduct

试图获取参数化的函数,该函数将返回特征的指定副产物。

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 个答案:

答案 0 :(得分:2)

您可以为A使用TypeTag并将其与Cl1Cl2进行比较:

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,但可以肯定地做到了) t同时为Cl1Cl2)。旁注:GADTs实际上由编译器进行了一些特殊处理,允许出现这种情况,例如:

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?
  }
}

顺便说一句,您的问题是人为的例子还是真实的场景?如果是后者,我认为应该可以以更优雅的方式实现它。