(我正在使用 Scala nightlies,并在 2.8.0b1 RC4 中看到相同的行为。我是 Scala 新手。)
我有两个 SortedMap
s,我想组建工会。这是我想使用的代码:
import scala.collection._
object ViewBoundExample {
class X
def combine[Y](a: SortedMap[X, Y], b: SortedMap[X, Y]): SortedMap[X, Y] = {
a ++ b
}
implicit def orderedX(x: X): Ordered[X] = new Ordered[X] { def compare(that: X) = 0 }
}
这里的想法是“隐式”声明意味着
X
s 可以转换为 Ordered[X]
s,然后组合 SortedMap
是有意义的换成另一个 SortedMap
,而不仅仅是一张 map 。当我编译时,我得到
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac -versionScala compiler version
2.8.0.Beta1-RC4 -- Copyright 2002-2010, LAMP/EPFL
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac ViewBoundExample.scala
ViewBoundExample.scala:8: error: type arguments [ViewBoundExample.X] do not
conform to method ordered's type parameter bounds [A <: scala.math.Ordered[A]]
a ++ b
^
one error found
如果该类型参数绑定(bind)是
[A <% scala.math.Ordered[A]]
,我的问题似乎会消失。 ,而不是 [A <: scala.math.Ordered[A]]
.不幸的是,我什至无法弄清楚“有序”方法的位置!任何人都可以帮我追踪它吗?如果做不到这一点,我该怎么做才能产生两个
SortedMap
的联合?年代?如果我删除 combine 的返回类型(或将其更改为 Map
)一切正常 --- 但是我不能依赖返回被排序!
最佳答案
目前,您使用的是 scala.collection.SortedMap
特征,其 ++
方法继承自 MapLike
特征。因此,您会看到以下行为:
scala> import scala.collection.SortedMap
import scala.collection.SortedMap
scala> val a = SortedMap(1->2, 3->4)
a: scala.collection.SortedMap[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> val b = SortedMap(2->3, 4->5)
b: scala.collection.SortedMap[Int,Int] = Map(2 -> 3, 4 -> 5)
scala> a ++ b
res0: scala.collection.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
scala> b ++ a
res1: scala.collection.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
++
的返回结果的类型是 Map[Int, Int]
,因为这将是 ++
对象的 MapLike
方法返回的唯一类型。似乎 ++
保留了 SortedMap
的 sorted 属性,我猜这是因为 ++
使用抽象方法进行连接,并且这些抽象方法被定义为保持映射的顺序。要合并两个已排序的 map ,我建议您使用
scala.collection.immutable.SortedMap
。scala> import scala.collection.immutable.SortedMap
import scala.collection.immutable.SortedMap
scala> val a = SortedMap(1->2, 3->4)
a: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> val b = SortedMap(2->3, 4->5)
b: scala.collection.immutable.SortedMap[Int,Int] = Map(2 -> 3, 4 -> 5)
scala> a ++ b
res2: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
scala> b ++ a
res3: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
这个
SortedMap
特征的实现声明了一个 ++
方法,该方法返回一个 SortedMap
。现在有几个关于类型界限的问题的答案:
Ordered[T]
是一个特征,如果混合在一个类中,它指定可以使用 <
、 >
、 =
、 >=
、 <=
比较该类。你只需要定义抽象方法 compare(that: T)
,它返回 -1
为 this < that
, 1
为 this > that
和 0
为 this == that
。然后根据 compare
的结果在 trait 中实现所有其他方法。 T <% U
表示在 Scala 中绑定(bind)的 View 。这意味着 T
类型要么是 U
的子类型,要么可以通过范围内的隐式转换隐式转换为 U
。如果您放置 <%
但不使用 <:
,则代码有效,因为 X
不是 Ordered[X]
的子类型,但可以使用 Ordered[X]
隐式转换隐式转换为 OrderedX
。 编辑: 关于您的评论。如果您使用的是
scala.collection.immutable.SortedMap
,那么您仍在对接口(interface)而不是实现进行编程,因为不可变的 SortedMap
被定义为 trait
。您可以将其视为 scala.collection.SortedMap
的更特殊的特征,它提供额外的操作(如 ++
返回 SortedMap
)和不可变的属性。这符合 Scala 哲学——更喜欢不变性——因此我认为使用不可变 SortedMap
没有任何问题。在这种情况下,您可以保证结果肯定会排序,并且由于集合是不可变的,因此无法更改。尽管如此,我仍然觉得奇怪的是
scala.collection.SortedMap
不提供 ++
方法,结果女巫返回 SortedMap
。我所做的所有有限测试似乎表明,两个 scala.collection.SortedMap
的串联结果确实产生了一个保留排序属性的映射。
关于scala - 如何形成 scala SortedMaps 的联合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1938038/