scala - 集合中通用多态数据的上下文边界

标签 scala generics polymorphism implicit

我有简化的情况:

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/

相关文章:

scala - Communicating Sequential Processes [CSP] 是 Scala 中actor模型的替代方案吗?

java - 将泛型类型对象写入 java 文件

c++ - 智能指针和 dynamic_cast

swift - 在函数定义中将泛型类型定义为协议(protocol)类型

java - 实现通用顶点和边类

java - 基于访问器方法强制执行严格继承

c++ - 测试一个类是否是多态的

scala - 如何在 Scala 中的对象中 stub protected 方法

scala - 计算spark中数字列的第一个四分位数

scala - 使用不同的 StreamingContext 相继打开两个 KafkaStream