在 Scala 的 Map 上键入级别插入和检索特定值
Type level insert and retrieve a certain value on a Map in Scala
给定一个(操作类似的数据结构)Map
。是否有类型级别的插入方式?即:
val myMap: Map[Int, String] = Map(1 -> "a", 2 -> "b")
val x: Int = 5
val y: Int = 99
val myMap2 = myMap + (x -> "e")
我希望的是 myMap2
将有某种类型,我可以在其中安全地执行类似 myMap2.retrieve(x)
的操作并编译它和 return "e"
。但是 myMap2.retrieve(y)
甚至不应该编译。
每次使用 myMap2.get(y)
时,如果 y 是 Int
,您将得到一个 Option
的字符串。
如果您尝试使用任何其他类型,您将遇到编译异常。
例如:myMap2.get("y")
将引发类型不匹配。
所以如果key类型不对就无法编译。
如果您的密钥有不同的类型,Shapeless 是可能的:
import shapeless._
object _1
object _2
object _3
object _4
//-------------Map definition starts here----------------
class StaticMap1[K, V]
trait StaticMap1Like {
type M[T] <: StaticMap1[T, String]
private def add[T]: M[T] = (new StaticMap1[T, String] {}).asInstanceOf[M[T]]
implicit val __1 = add[_1.type] //add key to StaticMap1
implicit val __2 = add[_2.type] //add key to StaticMap1
}
object StaticMap1 extends StaticMap1Like
val hm = HMap[StaticMap1](_1 -> "a", _2 -> "b") //add values
//-------------Map definition ends here-----------------
scala> hm.get(_1)
res0: Option[String] = Some(a)
scala> hm.get(_2)
res1: Option[String] = Some(b)
scala> hm.get(_3) //compile-time error
<console>:18: error: could not find implicit value for parameter ev: BiMapIS[shapeless.nat._3,V]
hm.get(_3)
^
和键插入:
//----Adding element _3 -> "c" starts here--------------
class StaticMap2[K, V] extends StaticMap1[K, V]
trait StaticMap2Like extends StaticMap1Like {
type M[T] <: StaticMap2[T, String]
private def add[T] = new StaticMap2[T, String] {}.asInstanceOf[M[T]]
implicit val __3 = add[_3.type] //add key to StaticMap2
}
object StaticMap2 extends StaticMap2Like
val hm2 = hm.asInstanceOf[HMap[StaticMap2]] + (_3 -> "c")
//----Adding element ends here---------------------------
scala> hm2.get(_3)
res6: Option[String] = Some(c)
scala> hm2.get(_2)
res7: Option[String] = Some(b)
scala> hm2.get(_1)
res8: Option[String] = Some(a)
scala> hm2.get(_4)
<console>:21: error: could not find implicit value for parameter ev: StaticMap2[_4.type,V]
hm2.get(_4)
^
scala> hm.get(_3) //old `hm` still working
<console>:17: error: could not find implicit value for parameter ev: StaticMap1[_3.type,V]
hm.get(_3)
^
但是:
- 不要在这里使用 Shapeless native
nat
- 它不会工作,因为它无法区分 nat._1
和 nat._2
(至少对于我的 Shapeless 版本)
- 向
Map
添加元素也不会那么方便,因为用户将不得不为每个新键添加一个隐含的
给定一个(操作类似的数据结构)Map
。是否有类型级别的插入方式?即:
val myMap: Map[Int, String] = Map(1 -> "a", 2 -> "b")
val x: Int = 5
val y: Int = 99
val myMap2 = myMap + (x -> "e")
我希望的是 myMap2
将有某种类型,我可以在其中安全地执行类似 myMap2.retrieve(x)
的操作并编译它和 return "e"
。但是 myMap2.retrieve(y)
甚至不应该编译。
每次使用 myMap2.get(y)
时,如果 y 是 Int
,您将得到一个 Option
的字符串。
如果您尝试使用任何其他类型,您将遇到编译异常。
例如:myMap2.get("y")
将引发类型不匹配。
所以如果key类型不对就无法编译。
如果您的密钥有不同的类型,Shapeless 是可能的:
import shapeless._
object _1
object _2
object _3
object _4
//-------------Map definition starts here----------------
class StaticMap1[K, V]
trait StaticMap1Like {
type M[T] <: StaticMap1[T, String]
private def add[T]: M[T] = (new StaticMap1[T, String] {}).asInstanceOf[M[T]]
implicit val __1 = add[_1.type] //add key to StaticMap1
implicit val __2 = add[_2.type] //add key to StaticMap1
}
object StaticMap1 extends StaticMap1Like
val hm = HMap[StaticMap1](_1 -> "a", _2 -> "b") //add values
//-------------Map definition ends here-----------------
scala> hm.get(_1)
res0: Option[String] = Some(a)
scala> hm.get(_2)
res1: Option[String] = Some(b)
scala> hm.get(_3) //compile-time error
<console>:18: error: could not find implicit value for parameter ev: BiMapIS[shapeless.nat._3,V]
hm.get(_3)
^
和键插入:
//----Adding element _3 -> "c" starts here--------------
class StaticMap2[K, V] extends StaticMap1[K, V]
trait StaticMap2Like extends StaticMap1Like {
type M[T] <: StaticMap2[T, String]
private def add[T] = new StaticMap2[T, String] {}.asInstanceOf[M[T]]
implicit val __3 = add[_3.type] //add key to StaticMap2
}
object StaticMap2 extends StaticMap2Like
val hm2 = hm.asInstanceOf[HMap[StaticMap2]] + (_3 -> "c")
//----Adding element ends here---------------------------
scala> hm2.get(_3)
res6: Option[String] = Some(c)
scala> hm2.get(_2)
res7: Option[String] = Some(b)
scala> hm2.get(_1)
res8: Option[String] = Some(a)
scala> hm2.get(_4)
<console>:21: error: could not find implicit value for parameter ev: StaticMap2[_4.type,V]
hm2.get(_4)
^
scala> hm.get(_3) //old `hm` still working
<console>:17: error: could not find implicit value for parameter ev: StaticMap1[_3.type,V]
hm.get(_3)
^
但是:
- 不要在这里使用 Shapeless native
nat
- 它不会工作,因为它无法区分nat._1
和nat._2
(至少对于我的 Shapeless 版本) - 向
Map
添加元素也不会那么方便,因为用户将不得不为每个新键添加一个隐含的