假设我想定义一些泛型类型,并保证只有当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可以是String
或Int
,但没有别的。我可以在以下函数中利用这些信息
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
)