扩展我之前关于HList
s 的评论:(这对于评论来说太大了,因此将其发布为答案。)
我在代码示例中使用了 Scala,因为它对正在讨论的想法有很好的支持。所有代码示例都在控制台输入。
当你有一个 type 的对象Dog
和另一个 type 的对象时Tiger
,如果你把它们放在同一个协变列表中,结果列表的类型List[Animal]
将Animal
是它们共同的超类型。因为这个列表是同质的,所以原始类型丢失了。请注意以下列表的推断类型:
scala> class Animal
defined class Animal
scala> class Dog extends Animal
defined class Dog
scala> class Tiger extends Animal
defined class Tiger
scala> List(new Tiger, new Dog)
res0: List[Animal] = List(Tiger@a32604, Dog@1150b68)
同样Verifier[Int]
,Verifier[String]
当放入单个同质列表时,将采用 type Verifier[Any]
。(在 Scala 中,Any
类位于对象层次结构的顶部。)请参阅:
scala> class Verifier[+T](value: T) {
| override def toString = "Verifier(" + value.toString + ")"
| }
defined class Verifier
scala> List(new Verifier(6), new Verifier("hello"))
res1: List[Verifier[Any]] = List(Verifier(6), Verifier(hello))
如果要保留静态类型,并将它们用于以后的计算,则应使用异构列表。或HList
简称。
scala> new Verifier(6) :: new Verifier("hello") :: HNil
res2: shapeless.::[Verifier[Int],shapeless.::[Verifier[java.lang.String],shapeless.HNil]] = Verifier(6) :: Verifier(hello) :: HNil
以下是多态映射的工作原理:
scala> class Parameter[+T](value: String, verif: Verifier[T]) {
| override def toString = "P(" + value + ", " + verif + ")"
| }
defined class Parameter
scala> object mapper extends (Verifier ~> Parameter) {
| def apply[A](v: Verifier[A]): Parameter[A] = new Parameter("k", v)
| }
defined module mapper
scala> res2 map mapper
res3: mapper.Out = P(k, Verifier(6)) :: P(k, Verifier(hello)) :: HNil
我们保留了类型参数,并使用给定的更高级别的函数作用于列表的每个元素。这让我们返回了 a HList
of Parameter
s,其中保留了正确的类型。
请注意,HList
可以在 Java 中实现的概念,但是您不能在结构上定义许多有用的操作。Java 的类型系统无法做到这一点。如果您有兴趣,这里有一篇关于该主题的精彩文章。
希望这在某种程度上有所帮助。