Scala Universal vs Existential类型的混淆

时间:2016-05-15 15:47:10

标签: java scala existential-type

this answer中它说......

  // Universal types let you write things like:

  def combine[T](source: List[T], dest: List[T]): List[T] = {
    source ++ dest
  }

但我不明白这个解释。

有人可以解释上面的通用类型示例和下面的一些类似示例(包含存在类型)之间的区别吗?

  def combine2[_](source: List[_], dest: List[_]): List[_] = {
    source ++ dest
  }


  def combine3(source: List[_], dest: List[_]): List[_] = {
    source ++ dest
  }

  def combine4[A, B](source: List[A], dest: List[B]): List[_] = {
    source ++ dest
  }

  def combine5[T](source: List[T], dest: List[T] forSome {type T}): List[T] forSome {type T} = {
    source ++ dest
  }

Java for good measure ...

public static List<?> combine6(final List<?> source, final List<?> dest) {
    return source;
}

// Why doesn't this compile? 
public static <T> List<T> combine7(final List<?> source, final List<?> dest) {
    return source;
}

另外,如果我提供类型标签,这是否会以任何方式取代对存在类型的需求?

  def combineTypetag[A, B, C](source: List[A], dest: List[B]) 
  (implicit tagA: TypeTag[A], tagB: TypeTag[B], tagC: TypeTag[C]): List[C] = {
    source ++ dest
  }

1 个答案:

答案 0 :(得分:3)

val list1: List[Int] = ... val list2: List[Int] = ... val list3 = combine(list1, list2) // also List[Int] val x = list3.head // Int val y = x + x // Int 表示如果您有两个具有相同元素类型的列表,则会返回相同的类型,例如:

combine

val list1: List[FileInputStream] = ... val list2: List[ByteArrayInputStream] = ... val list3 = combine(list1, list2) // List[InputStream] 也可以与不同类型的列表一起使用,并返回最精确的常见类型:

List[T] forSome {type T}

所有其他选项都返回List[_],即某些未知类型的列表(val list1: List[Int] = ... val list2: List[Int] = ... val list4 = combine2(list1, list2) // List[_] val z = list4.head // Any val w = z + z // doesn't compile 只是写这个的简短方法):

List<?> list = Arrays.asList("a", "b");
List<Integer> list2 = <Integer>combine7(list, list);

所以他们只是丢失了类型信息。只有当不能更精确时,才能使用存在类型。

  

为什么不编译?

如果确实如此,你期望在这里发生什么:

HOMES

  

另外,如果我提供类型标签,这是否会以任何方式取代对存在类型的需求?

这里不需要存在类型,但是当存在时,类型标签不会有帮助:根据定义,编译器只能在知道静态类型是什么时才插入类型标记,因此存在类型不是&# 39; t需要。