0

Trying to get a parametrized function that would return the specified coproduct of a trait.

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

How can this be achieved in Scala 2.11?

Vasily802
  • 1,314
  • 16
  • 28

1 Answers1

2

You could use a TypeTag for A and compare it to Cl1 and 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)

Note that I had to change the return type to Tr. It can't work with A because the compiler wouldn't allow having branches that resolve into different types for A (we don't know the actual A, but it surely can't be both Cl1 and Cl2 at the same time). Side note: GADTs actually have a bit of special treatment by the compiler which allows such cases, e.g.:

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

By the way, is your question a contrived example or a real scenario? If it's the latter, I feel it should be possible to implement it in a more elegant way.

slouc
  • 8,715
  • 3
  • 13
  • 36