【问题标题】:Real example of "Can all usages of `forSome` be replaced by an equivalent usage of `_`?"“可以用 `_` 的等效用法代替所有 `forSome` 的用法吗?”的真实示例
【发布时间】:2014-05-05 04:34:11
【问题描述】:

我看到了问题的答案:Can all usages of forSome be replaced by an equivalent usage of _?, 但不明白不能使用“_”代替“forSome”的真实情况是什么。 我在Programming in Scala 书中读到:

存在类型是该语言完全支持的部分,但在 实践它们主要用于从 Scala 访问 Java 类型时。 我创建了 Scala 项目并引用了 Java 之一:

斯卡拉:

object Main {
  def main(args: Array[String]): Unit = {
    type Test = java.util.Collection[T] forSome { type T }
    val contents: Test = (new Wild).contents

    type Test2 = java.util.Collection[_]
    val contents2: Test2 = (new Wild).contents

    //    foo((new Wild).contents2) // won't compile

    foo1((new Wild).contents2)
    foo1((new Wild).contents3)

    foo2((new Wild).contents3)
  }

  def foo(xs: java.util.Map[T, T] forSome { type T }) {}
  def foo1(xs: java.util.Map[_, _]) {}
  def foo2(xs: java.util.Map[_, _ <: java.lang.Number]) {}
}

Java:

public class Wild {
    public Collection<?> contents() {
        return null;
    }
    public Map<?, ?> contents2() {
        return null;
    }
    public Map<?, ? extends Number> contents3() {
        return null;
    }
}

在所有情况下,我都能将“forSome”替换为“_”。 那么需要“forSome”的真实案例是什么?请提供简单的工作示例。

【问题讨论】:

    标签: scala


    【解决方案1】:

    这是一个相当简单的例子。

    val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
    

    请注意,我只能将 same 包含类型的集合存储到列表中。我不能做例如这个:

    val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set("a", "b", "c"))
    

    listOfSets 的类型没有forSome 是无法表达的。确实,

    val listOfSets2: List[Set[_]]
    

    等价于

    val listOfSets2: List[Set[T] forSome { type T }]
    

    这意味着列表可以包含不同类型的集合,所以这两种方法都有效:

    val listOfSets2: List[Set[_]] = List(Set(1, 2, 3), Set(4, 5, 6))
    val listOfSets2: List[Set[_]] = List(Set(1, 2, 3), Set("a", "b", "c"))
    

    有趣的是,如果您以 scala -feature 运行 Scala 解释器并尝试执行此答案中的第一行代码,您将收到关于通配符存在类型不可表达性的警告:

    scala> val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
    <console>:7: warning: the existential type List[Set[T]] forSome { type T }, which cannot be expressed by wildcards,  should be enabled
    by making the implicit value scala.language.existentials visible.
    This can be achieved by adding the import clause 'import scala.language.existentials'
    or by setting the compiler option -language:existentials.
    See the Scala docs for value scala.language.existentials for a discussion
    why the feature should be explicitly enabled.
           val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
                                         ^
    listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
    

    还有一个例子。假设您要将一个类映射到该类的单个实例。这可以用这种类型表示:

    val classInstanceMap: Map[Class[T], T] forSome { type T }
    

    没有forSome,你就不能写出正确的类型——没有其他方法可以“关联”键和值的类型。比如这种带通配符的类型:

    val invalidClassInstanceMap: Map[Class[_], _]
    

    等价于

    val invalidClassInstanceMap: Map[Class[K] forSome { type K }, V] forSome { type V }
    

    这里KV根本不相关,而且,键可以是任意Class[T]的任意实例T,但所有值都应该具有相同的类型。

    【讨论】:

      猜你喜欢
      • 2012-03-15
      • 2013-10-19
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-28
      相关资源
      最近更新 更多