Правильный способ сделать это требует некоторой сантехники: используйте Coproduct
, чтобы перечислить все возможные значения:
class BiMapIS[K, V] { type Value = V }
implicit object strKey extends BiMapIS[String, Coproduct.`Int, String`.T]
implicit object intKey extends BiMapIS[Int, Coproduct.`Boolean`.T]
val hm = HMap[BiMapIS](
"val1" -> Coproduct[strKey.Value](1),
"val2" -> Coproduct[strKey.Value]("two"),
3 -> Coproduct[intKey.Value](true)
)
Затем вы можете сделать себя полезным классом ops для облегчения получения значений изHMap
:
implicit class HMapOps[R[_,_]](hm: HMap[R]) {
def atKey[K,C <: Coproduct](k: K)(implicit ev1: R[K, C]) = new {
def withValueType[V](implicit ev2: shapeless.ops.coproduct.Selector[C, V]): Option[V] =
hm.get(k).flatMap(_.select[V])
}
}
Собираем все вместе:
scala> hm.atKey("val1").withValueType[Int]
res1: Option[Int] = Some(1)
scala> hm.atKey("val1").withValueType[String]
res2: Option[String] = None
scala> hm.atKey("val1").withValueType[Boolean] // String never maps to Boolean!!!
<console>: error: could not find implicit value for parameter ev2: shapeless.ops.coproduct.Selector[shapeless.:+:[Int,shapeless.:+:[String,shapeless.CNil]],Boolean]
hm.atKey("val1").withValueType[Boolean]