加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在Scala泛型语法中放置“forSome”子句有什么重要意义?

发布时间:2020-12-16 18:38:48 所属栏目:安全 来源:网络整理
导读:基于 this question的答案,似乎在类型定义的组件之后放置“forSome”与将其放在整个事件的末尾不同.例如,似乎以下内容之间存在差异: def one: Foo[U : T] forSome {type U : T}def one: Foo[U forSome {type U : T}] Scala语言规范似乎没有说明差异,我想象
基于 this question的答案,似乎在类型定义的组件之后放置“forSome”与将其放在整个事件的末尾不同.例如,似乎以下内容之间存在差异:

def one: Foo[U >: T] forSome {type U >: T}

def one: Foo[U forSome {type U >: T}]

Scala语言规范似乎没有说明差异,我想象将量词转移到外部没有任何区别.如果它确实有所作为,我认为它将如this answer所述,基本上说Set [X forSome {type X}]允许X在set元素之间变化,其中Set [X] forSome {type X}不.但是,这似乎不是整个故事和/或不正确,因为这不编译:

trait Bar {
   def test: Set[X] forSome {type X}
}

def test(b: Bar) {
  val set = b.test
  val h = set.head
  set.contains(h)
}

但这样做:

trait Bar {
   def test: Set[X forSome {type X}]
}

def test(b: Bar) {
  val set = b.test
  val h = set.head
  set.contains(h)
}

似乎Set [X] forSome {type X}为实例化类中的每个使用站点创建一个单独的抽象类型,其中Set [X forSome {type X}]仅创建一个并将其用于整个类.这与我的预期相反,似乎与上面的答案参考不一致.

解决方法

一些观察开始:X forSome {type X}只是一种奇特的编写方式Any-it是一种我们什么都不知道的类型,因此它必须位于类型层次结构的顶部.如果你不相信我,请问编译器:

scala> implicitly[Any =:= X forSome { type X }]
res0: =:=[Any,_] = <function1>

是的,它同意.

相关地,以下内容不会编译:

scala> val xs: Set[X forSome { type X }] = Set[Int](1,2,3)
<console>:7: error: type mismatch;
 found   : scala.collection.immutable.Set[Int]
 required: Set[X forSome { type X }]
Note: Int <: X forSome { type X },but trait Set is invariant in type A.

鉴于我们刚刚学到的东西,这并不奇怪. Set在其类型参数中是不变的,因此Set [Int]不是Set [X forSome {type X}](即,Set [Any]).

考虑到所有这一点,第二种测试方法编译也就不足为奇了.当我们取b.test的头部时,我们得到一个X forSome {type X}(即Any),我们需要一个X forSome {type X}(即Any)用于b.test.contains.

所以现在为第一个吧.考虑以下:

scala> val xs: Set[X] forSome { type X } = Set[Int](1,3)
xs: Set[_] = Set(1,3)

这里我们说过xs是一些特定类型X的集合,但我们会立即忘记关于X的所有内容.请注意,与上面的xs定义不同,这会编译,因为我们并不是说xs是一个集合任何事情,只是它是一组我们不知道的特定类型(或者说编译器不知道).

这意味着绝对没有可能使xs.contains(a)编译.让我们尝试一个明显的:

scala> xs.contains(1)
<console>:9: error: type mismatch;
 found   : Int(1)
 required: X
              xs.contains(1)
                          ^

这里的错误消息很有趣 – 我们知道X实际上是Int,但编译器没有,因为我们明确要求它忘记了forSome {type X}的事实.您可以通过重写第一个Bar的测试方法来查看类似的有趣消息,如下所示:

def test(b: Bar) = b.test.contains(b.test.head)

这也将无法编译,并显示以下消息:

found   : (some other)X(in method test) where type (some other)X(in method test)
required: X(in method test) where type X(in method test)
      def test(b: Bar) = b.test.contains(b.test.head)
                                             ^

也就是说,即使我们将b.test.head从b.test中拉出来,我们仍然无法将b.test.contains应用于它.我们已经告诉编译器,它唯一知道的关于b.test的项类型是它存在,所以它不会跟踪b.test.head是我们应该做的事情的事实能够将b.test.contains应用于.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读