我有简化的情况:
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
现在我有一个 Map[String, Top]
并且想对 map 中所有需要 Typeclass
实例的值进行操作在上下文中可用。这不会编译,因为映射中值的具体类型从其类型中看不到,因此我无法为它们设置上下文绑定(bind)。
有没有办法告诉编译器事实上总会有一个实例可用?在这个例子中,这是给出的,因为有隐式函数可以为 Top
的每个具体子类型生成这些实例。
还是使用 HList
并递归其类型要求所有实例都在上下文中的唯一解决方案?
最佳答案
我建议对 Oleg 的 Existentials as universals 的这种改编使用一些变体在这种情况下......将类型类实例及其实例的值打包,
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
trait Pack {
type T <: Top
val top: T
implicit val tc: Typeclass[T]
}
object Pack {
def apply[T0 <: Top](t0: T0)(implicit tc0: Typeclass[T0]): Pack =
new Pack { type T = T0 ; val top = t0 ; val tc = tc0 }
}
val m = Map("a" -> Pack(new A[Int]), "b" -> Pack(new B[Double]))
def foo[T: Typeclass](t: T): Unit = ()
def bar(m: Map[String, Pack], k: String): Unit =
m.get(k).map { pack =>
import pack._ // imports T, top and implicit tc
foo(top) // instance available for call of foo
}
bar(m, "a")
关于scala - 集合中通用多态数据的上下文边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32049964/