将泛型类型限制为枚举类型

时间:2016-01-16 11:14:43

标签: scala generics enums typeclass

假设我想定义一些泛型类型,并保证只有当generic参数是已知类型列表之一时才会实例化它。使用类型类的一种方法是

sealed trait Allowed[A]
object Allowed {
  implicit object string extends Allowed[String]
  implicit object int extends Allowed[Int]
}
case class Player[A: Allowed](id: A, name: String, score: Double)

在这种情况下,我知道Player的ID可以是StringInt,但没有别的。我可以在以下函数中利用这些信息

def retrievePlayerById[A: Allowed](p: Player[A]) =
  implicitly[Allowed[A]] match {
    case Allowed.string =>
      val id = p.id.asInstanceOf[String]
      ...
    case Allowed.int =>
      val id = p.id.asInstanceOf[Int]
      ...
  }

现在,我的问题如下。我想做同样的事情,但允许泛型参数是String或任何枚举类型。

如果枚举要像这样编码,我不在乎:

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

或者像这样

trait WeekDay
case object Mon extends WeekDay
case object Tue extends WeekDay
case object Wed extends WeekDay
case object Thu extends WeekDay
case object Fri extends WeekDay
case object Sat extends WeekDay
case object Sun extends WeekDay

虽然前者因其他原因会更方便一些。

任何想法如何做到这一点?

编辑:首次尝试就像这样

sealed trait Allowed[A]
object Allowed {
  implicit object string extends Allowed[String]
  implicit def enum[A <: Enumeration] = new Allowed[A#Value] {}
}

这适用于限制类型,现在问题是模式匹配。我能做到

def foo[A: Allowed] = implicitly[Allowed[A]] match {
  case Allowed.string =>
    // everything ok in this branch
  case _ =>
    // here I don't know how to persuade the compiler that A is
    // an enumeration type
}

为了说服编译器我有一个枚举类型,我也尝试与

匹配
case n: Allowed[(A forSome { type A <: Enumeration })#Value] =>

或类似地

case n: Allowed[A#Value forSome { type A <: Enumeration }] =>

但编译器拒绝两者都说Value不是A的类型成员(即使我约束A来扩展Enumeration

0 个答案:

没有答案