Generics 相关参数化类型

Generics 相关参数化类型,generics,scala,Generics,Scala,我有一个映射,其中键和值都是泛型类型。大概是这样的: Map[Foo[A], Bar[A]] object Example { type Identity[T] = T type Handler[T] = (T) => _ val handlers = new HMap[Identity, Handler] def doSomething() { for (HMap.Mapping(value, handler) <- handlers) {

我有一个映射,其中键和值都是泛型类型。大概是这样的:

Map[Foo[A], Bar[A]]
object Example {
  type Identity[T] = T
  type Handler[T] = (T) => _

  val handlers = new HMap[Identity, Handler]

  def doSomething() {
    for (HMap.Mapping(value, handler) <- handlers) {
      handler(value)
    }
  }
}
我想表达的是,映射中的每个键-值对的类型
A
可能不同,但每个键总是使用与其映射到的值相同的类型进行参数化。所以
Foo[Int]
总是映射到
Bar[Int]
Foo[String]
总是映射到
Bar[String]
,依此类推

有人知道如何表达这一点吗

编辑:

下面是我正在尝试做的事情的一个例子:

trait Parameter // not important what it actually does

class Example {
  val handlers: Map[_ <: Parameter, (_ <: Parameter) => _] = Map()

  def doSomething() {
    for ((value, handler) <- handlers) {
      handler(value)
    }
  }
}
trait参数//它的实际功能并不重要
课例{

val handlers:Map[\p>您试图描述一种异构映射,映射中的每个键值对都可以有不同的类型参数。尽管很酷,Scala的类型系统不允许您静态地表达这一点。我认为您最好定义一些可怕的、不安全的帮助器方法:

def-get[A](映射:映射[Foo[\u],条[\u]],k:Foo[A]):条[A]
def put[A](映射:映射[Foo[\uz]、条[\uz]、k:Foo[A]、v:Bar[A])
您可以在运行时使用
Manifest
s来具体化每个键值对的类型参数,使其更加安全,但我不确定如何…

scala>trait MyPair{
scala> trait MyPair {
     | type T
     | val key:Foo[T]
     | val value:Bar[T]
     | }
defined trait MyPair

scala> var l:List[MyPair] = _
l: List[MyPair] = null

scala> l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} })
l: List[MyPair] = List($anon$1@176bf9e)

scala> l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} }, new MyPair {type T = String; val key = new Foo[String]{}; val value = new Bar[String]{} })
l: List[MyPair] = List($anon$1@d78fb4, $anon$4@1b72da)

scala> l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} }, new MyPair {type T = String; val key = new Foo[String]{}; val value = new Bar[Int]{} })
<console>:11: error: overriding value value in trait MyPair of type Bar[this.T];
 value value has incompatible type
       l = List(new MyPair{type T = Int; val key = new Foo[Int]{}; val value = new Bar[Int]{} }, new MyPair {type T = String; val key = new Foo[String]{}; val value = new Bar[Int]{} })
|T型 |val key:Foo[T] |val值:巴[T] | } 定义特征对 scala>var l:List[MyPair]=_ l:列表[MyPair]=null scala>l=List(新的MyPair{type T=Int;val-key=new-Foo[Int]{};val-value=new-Bar[Int]{}) l:List[MyPair]=List($anon)$1@176bf9e) scala>l=List(新的MyPair{type T=Int;val-key=new-Foo[Int]{};val-value=new-Bar[Int]{},新的MyPair{type T=String;val-key=new-Foo[String]{};val-value=new-Bar[String]{}) l:List[MyPair]=List($anon)$1@d78fb4,$anon$4@1b72da) scala>l=List(新的MyPair{type T=Int;val-key=new-Foo[Int]{};val-value=new-Bar[Int]{},新的MyPair{type T=String;val-key=new-Foo[String]{};val-value=new-Bar[Int]{}) :11:错误:重写类型为Bar[this.T]的trait MyPair中的值; 值的类型不兼容 l=List(新的MyPair{type T=Int;val key=new Foo[Int]{};val value=new Bar[Int]{},新的MyPair{type T=String;val key=new Foo[String]{};val value=new Bar[Int]{})
事实证明,可以在Scala中定义异构映射。下面是一个大致示意图:

class HMap[A[_], B[_]] extends Iterable[HMap.Mapping[A, B, _]] {
  private val self = mutable.Map[A[_], B[_]]()

  def toMapping[T](a: A[_], b: B[_]): HMap.Mapping[A, B, T] = {
    HMap.Mapping(a.asInstanceOf[A[T]], b.asInstanceOf[B[T]])
  }

  def iterator: Iterator[HMap.Mapping[A, B, _]] =
    new Iterator[HMap.Mapping[A, B, _]] {
      val sub = self.iterator

      def hasNext = sub.hasNext
      def next(): HMap.Mapping[A, B, _] = {
        val (key, value) = sub.next()
        toMapping(key, value)
      }
    }

  def update[T](key: A[T], value: B[T]) = (self(key) = value)
  def get[T](key: A[T]) = self.get(key).asInstanceOf[Option[B[T]]]
  def apply[T](key: A[T]) = self(key).asInstanceOf[B[T]]
}

object HMap {
  case class Mapping[A[_], B[_], T](val key: A[T], val value: B[T])
}
通过在内部使用映射的链表而不是映射,可以使其完全类型安全,但这对性能更好

我最初的示例如下所示:

Map[Foo[A], Bar[A]]
object Example {
  type Identity[T] = T
  type Handler[T] = (T) => _

  val handlers = new HMap[Identity, Handler]

  def doSomething() {
    for (HMap.Mapping(value, handler) <- handlers) {
      handler(value)
    }
  }
}
对象示例{
类型标识[T]=T
类型处理程序[T]=(T)=>_
val handlers=新的HMap[标识,处理程序]
def doSomething(){

对于(HMap.Mapping(value,handler)我已经实现了一个可以满足您需要的映射。您可以在这里找到一些关于它的基本文档:

TypeBoundMaps使用带有单个类型参数的类型,因此需要为映射中的键和值类型引入两种新类型:

trait Parameter
type Identity[P <: Parameter] = P
type Handler[P <: Parameter] = (P) => _
以下是使用地图的几个示例:

trait P1 extends Parameter
trait P2 extends Parameter

val p1: P1 = new P1 {}
val f1: Handler[P1] = { p1: P1 => () }

handlers += p1 -> f1 // add a new pair to the map                                                             
val f2: Handler[P1] = handlers(p1) // retrieve a value from the map
现在,为了模拟示例中的for循环,我们需要引入一个新类型
TypeBoundPair
,这是一个参数值匹配的键值对:

def handle[P <: Parameter](pair: TypeBoundPair[Parameter, Identity, Handler, P]): Unit = {
  pair._2(pair._1)
}

handlers.foreach { pair => handle(pair) }
def handle[P handle(对)}

这里更详细地解释了引入
Identity
Handler
类型背后的思想:

这一行不是自己编译的,scala需要从某个地方选择这些类型(类或方法类型注释,或抽象类型)你能给我们看一下代码吗?这几乎是重复的,它们应该是封装不安全映射的对象中的方法-然后用户会得到一个更安全的接口(或者甚至是一个安全的接口,如果条目只能通过该接口插入;但这通常限制太多)。基本接口不需要清单。实现当然需要使用强制转换,但您可以确保它们不会失败。