如何在Scala3/Dotty中实现像MapK这样的类型?
我正在尝试但未能让这样的东西在 Scala 3 中工作:
type TupleK[K[*], V[*], A] = (K[A], V[A])
final class MapK[K[*], V[*]] private (val rawMap: Map[K[?], V[?]]) {
def foreach(f: TupleK[K, V, ?] => Unit): Unit = {
rawMap.foreach(f.asInstanceOf[Tuple2[K[?], V[?]] => Any])
}
}
object MapK {
def apply[K[*], V[*]](entries: TupleK[K, V, ?]*): MapK[K, V] = {
new MapK[K, V](Map(entries: _*))
}
}
像这样使用:
class Key[A]()
type Id[A] = A
val intKey = Key[Int]
val strKey = Key[String]
MapK[Key, Id](intKey -> 1, strKey -> "a")
在 Scala 2 中,只需要通过替换*和?使用来调整语法_(_*当然除外)。
然而,在 Scala 3 中,基本上每一行都会出现“无法将更高类型的类型应用于通配符参数”的错误:Scastie。
文档说Scala 3 中已经删除了存在类型,但是他们并没有真正给出任何关于如何处理这个问题的重要示例。
文档提到“存在类型与依赖路径的类型在很大程度上重叠”——这个 MapK 可以用依赖路径的类型来实现吗?我读过这个,但不明白如何应用它,或者在我的情况下是否可行。
而且,如果不是路径依赖类型……那又如何?Scala 似乎不太可能被“简化”到无法再实现此功能的地步,所以我一定遗漏了一些东西。
ETA:除了下面我自己的答案之外,我还制作了这个 repo并写了这篇关于在 Scala 3 中编码 MapK 的各种方法的文章。