Scala逆变 – 现实生活中的例子
我了解scala中的协方差和相反性。协方差在现实世界中有许多应用,但除了功能的旧例子外,我不能想到任何违反应用的应用。
有人可以对现实世界的逆向使用举例说明一些吗? 解决方法
在我看来,功能之后的两个最简单的例子是排序和平等。但是,Scala的标准库中第一个并不是矛盾的,第二个不存在于此。所以,我将使用Scalaz的等价物:
Order和
Equal。
接下来,我需要一些类层次结构,最好是熟悉的层次结构,当然,上述这两个概念都必须有意义。如果Scala具有所有数字类型的Number超类,那将是完美的。不幸的是,它没有这样的东西。 所以我要尝试用集合来制作这些例子。为了简单起见,我们来考虑Seq [Int]和List [Int]。应该清楚的是List [Int]是Seq [Int]的子类型,即List [Int]< ;: 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]]< ;: Order [List [Int]]。鉴于Seq [Int]> ;: 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是对比变体。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |