Frage

I wonder whether using generics for Scala case classes can save some boilerplate code.

Let's save I have the following class hieararchy to emulate a "variant" type that boxes a set of types and allows unboxing them using pattern matching:

sealed abstract class Box;

case class DoubleBox(v: Double) extends Box;
case class StringBox(v: String) extends Box;
case class BooleanBox(v: Boolean) extends Box;

def typeName(b: Box) = b match {
  case DoubleBox(v) => "Double"
  case StringBox(v) => "String"
  case BooleanBox(v) => "Boolean"
  case _ => "Unknown"
}

There may be places in the code where it would be more convenient to deal with the leaf case classes if they were generics. Something like:

sealed abstract class Box;

case class TypedBox[T](v: T) extends Box;

def typeName2(b: Box) = b match {
  case TypedBox[Double](v) => "Double"
  case TypedBox[String](v) => "String"
  case TypedBox[Boolean](v) => "Boolean"
  case _ => "Unknown"
}

But this doesn't compile. As far as I understand this syntax is not really recognized as valid Scala syntax.

Is it possible to make what I want working or it's a bad idea and I just don't get something?

EDIT: Vinicius answered my question, but looking at the answer I have another question. Is it possible to hint the compiler somehow that only certain list of types can be used to parameters TypedBox? I want that to make sure the compiler can still do exhaustiveness check of TypedBox usage/matching.

War es hilfreich?

Lösung

Try

sealed abstract class Box;

case class TypedBox[T](v: T) extends Box;

def typeName2(b: Box) = b match {
  case TypedBox(v: Double) => "Double"
  case TypedBox(v: String) => "String"
  case TypedBox(v: Boolean) => "Boolean"
  case _ => "Unknown"
}

Andere Tipps

For the second part of the question, there are two ways to limit the allowed types.

The first would be to put a bound on the type, which would limit the allowable types, but would not allow the compiler to do meaningful completeness checks as the types could be defined pretty much anywhere or any time.

The second would be to wrap the type in a sealed trait, but then you are essentially creating a case class for each type, so you might as well remove the extra layer of wrapping and simply create DoubleBox, StringBox, etc.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top