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