我希望能够创建一个类似于枚举的类/特征(下面第一个片段中的HEnum
)。我不能使用普通枚举,因为每个枚举值可以有不同的类型(虽然容器类将是相同的):Key[A]
。我希望能够像这样构建枚举:
class Key[A](val name: String)
object A extends HEnum {
val a = new Key[String]("a")
val b = new Key[Int]("b")
val c = new Key[Float]("c")
}
然后我希望能够执行或多或少的基本HList
操作,例如:
A.find[String] // returns the first element with type Key[String]
A.find("b") // returns the first element with name "b", type should (hopefully) be Key[Int]
到目前为止,我一直在使用HList
作为基础数据结构,但是使用正确的类型构建一个已经证明是困难的。我最成功的尝试是这样的:
class Key[A](val name: String)
object Key {
def apply[A, L <: HList](name: String, l: L): (Key[A], Key[A] :: L) = {
val key = new Key[A](name)
(key, key :: l)
}
}
object A {
val (a, akeys) = Key[String, HNil]("a", HNil)
val (b, bkeys) = Key[Int, Key[String] :: HList]("b", akeys)
val (c, ckeys) = Key[Float, Key[Int] :: HList]("c", bkeys)
val values = ckeys // use this for lookups, etc
def find[A]: Key[A] = values.select[A]
def find[A](name: String): Key[A] = ...
}
这里的问题是界面很笨重。在值列表末尾的任何位置添加新值都是容易出错的,无论如何,只要引入新值,就必须手动更新values
。没有HList
的解决方案在需要时会将List[Key[_]]
和容易出错/不安全的转换为正确类型。
修改
我还应该提一下,发现here的枚举示例对我没有特别的帮助(尽管如果可以调整,那么很好)。添加的编译器检查穷举模式匹配是很好的(我最终会想要),但这个枚举仍然只允许枚举值的同类集合。