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

Scala逆变 – 现实生活中的例子

发布时间:2020-12-16 09:44:51 所属栏目:安全 来源:网络整理
导读:我了解scala中的协方差和相反性。协方差在现实世界中有许多应用,但除了功能的旧例子外,我不能想到任何违反应用的应用。 有人可以对现实世界的逆向使用举例说明一些吗? 解决方法 在我看来,功能之后的两个最简单的例子是排序和平等。但是,Scala的标准库中
我了解scala中的协方差和相反性。协方差在现实世界中有许多应用,但除了功能的旧例子外,我不能想到任何违反应用的应用。

有人可以对现实世界的逆向使用举例说明一些吗?

解决方法

在我看来,功能之后的两个最简单的例子是排序和平等。但是,Scala的标准库中第一个并不是矛盾的,第二个不存在于此。所以,我将使用Scalaz的等价物: Order和 Equal。

接下来,我需要一些类层次结构,最好是熟悉的层次结构,当然,上述这两个概念都必须有意义。如果Scala具有所有数字类型的Number超类,那将是完美的。不幸的是,它没有这样的东西。

所以我要尝试用集合来制作这些例子。为了简单起见,我们来考虑Seq [Int]和List [Int]。应该清楚的是List [Int]是Seq [Int]的子类型,即List [Int]&lt ;: Seq [Int]。

那么我们该怎么办呢?首先,我们来写一些比较两个列表的东西:

def smaller(a: List[Int],b: List[Int])(implicit ord: Order[List[Int]]) =
  if (ord.order(a,b) == LT) a else b

现在我要为Seq [Int]编写一个隐式顺序:

implicit val seqOrder = new Order[Seq[Int]] { 
  def order(a: Seq[Int],b: Seq[Int]) = 
    if (a.size < b.size) LT
    else if (b.size < a.size) GT
    else EQ
}

有了这些定义,我现在可以这样做:

scala> smaller(List(1),List(1,2,3))
res0: List[Int] = List(1)

请注意,我要求一个订单[List [Int]],但是我正在传递一个订单[Seq [Int]]。这意味着Order [Seq [Int]]&lt ;: Order [List [Int]]。鉴于Seq [Int]&gt ;: List [Int],这是唯一可能的,因为反差。

接下来的问题是:它有什么意义吗?

让我们再考虑一下吧。我想比较两个整数列表。自然地,比较两个列表的任何东西都是可以接受的,但是比较两个Seq [Int]是可以接受的东西的逻辑是什么?

注意在seqOrder的定义中,如何比较的事情成为它的参数。显然,List [Int]可以作为期望Seq [Int]的某个参数。从那以后,一些比较Seq [Int]的东西可以接受来代替比较List [Int]的东西:它们都可以用于相同的参数。

反之如何?假设我有一个方法,只比较::(列表的cons),它与Nil一起是List的子类型。我显然不能使用这个,因为较小的可能会收到一个零比较。因此,不能使用Order [:: [Int]]而不是Order [List [Int]]。

让我们继续平等,并为此写一个方法:

def equalLists(a: List[Int],b: List[Int])(implicit eq: Equal[List[Int]]) = eq.equal(a,b)

因为Order扩展了等于,我可以使用它与上面相同的隐含:

scala> equalLists(List(4,5,6),3)) // we are comparing lengths!
res3: Boolean = true

这里的逻辑是一样的。任何可以判断两个Seq [Int]是否相同的事情,显然也可以告诉两个List [Int]是否相同。因此,等于[Seq [Int]] =等于[List [Int]],这是真的,因为Equal是对比变体。

(编辑:李大同)

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

    推荐文章
      热点阅读