使用 HMap 时隐式值不明确

Ambiguous Implicit Values when using HMap

HMap 似乎是我的用例的完美数据结构,但是,我无法让它工作:

case class Node[N](node: N)

class ImplVal[K, V]
implicit val iv1 = new ImplVal[Int, Node[Int]]
implicit val iv2 = new ImplVal[Int, Node[String]]
implicit val iv3 = new ImplVal[String, Node[Int]]

val hm = HMap[ImplVal](1 -> Node(1), 2 -> Node("two"), "three" -> Node(3))

我的第一个问题是是否可以自动创建这些 implicits vals。当然,对于典型的组合,我可以手动创建它们,但我想知道是否有更通用、更少样板的方式。

下一个问题是,如何从地图中获取值:

val res1 = hm.get(1) // (1) ambiguous implicit values: both value iv2 [...] and value iv1 [...] match expected type ImplVal[Int,V]`

对我来说,Node[Int] (iv1) 和 Node[String] (iv2) 看起来很不一样 :) 我认为,尽管存在 JVM 类型擦除限制,但 Scala 可以在此处区分。我错过了什么?我是否必须使用其他隐式值来明确区别?

显式版本有效:

val res2 = hm.get[Int, Node[Int]](1) // (2) works

当然,在这个简单的例子中,我可以将类型信息添加到 get 调用中。但是在下面的情况下,只有密钥是预先知道的,我不知道该怎么做:

def get[T <: HList](keys: T): HList = // return associated values for keys

这个问题有什么简单的解决办法吗?

顺便说一句,可以推荐哪些关于 Scala 类型系统(或 Shapeless 或一般函数式编程)的文档来更好地理解整个主题,我不得不承认,我缺乏关于这个主题的一些背景知识。

键的类型决定了值的类型。您有 Int 键对应于 Node[Int]Node[String] 值,因此存在歧义。您可能会发现 this article 有助于解释其背后的一般机制。