列挙型のように動作するクラス/特性を作成できるようにしたい (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[_]]
編集
また、ここで見つかった列挙型の例は特に役に立たないことにも言及する必要があります (ただし、それを適応させることができれば素晴らしいことです)。徹底的なパターン マッチのコンパイラ チェックが追加されたことは素晴らしいことですが (最終的にはそうしたいと思います)、この列挙型では依然として列挙値の同種のコレクションしか許可されません。