【问题标题】:Scala Universal vs Existential type confusionScala Universal vs Existential 类型混淆
【发布时间】:2016-09-11 10:35:16
【问题描述】:

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 衡量标准...

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
  }

【问题讨论】:

    标签: java scala existential-type


    【解决方案1】:

    combine 表示如果你有两个具有相同元素类型的列表,你会得到相同的类型,例如:

    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);
    

    ?

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

    这里不需要存在类型,但是如果有,类型标签也无济于事:编译器根据定义只能在知道静态类型是什么时插入类型标签,因此不需要存在类型.

    【讨论】:

    • 我可以将存在类型视为“不知道”类型吗?例如,source: List[_] 表示 source 的类型为 List["don't know"]。
    • 是的,它们就是这样。当然,如果您有多个List[_],那么那些_ 可能会有所不同。即使你作为程序员知道它们是相同的,编译器也不会(通常)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多