Scala:A 扩展 Ordered[A]
Scala: A extends Ordered[A]
我刚开始学习 Scala,为了练习,我决定创建一个 Pair[A, B] class,排序时将首先按 A 排序,然后按 B 排序。我的第一次尝试是这样的:
case class Pair[A <: Ordered[A], B <: Ordered[B]](val left: A, val right: B) extends Ordered[Pair[A, B]]
{
override def compare(that: Pair[A, B]) = {
val leftCompare = this.left.compare(that.left)
if (leftCompare == 0)
this.right.compare(that.right)
else
leftCompare
}
}
object Main extends App
{
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
}
这就是我想要的方式,真的。我想扩展 Ordered 并让它工作,所以我可以像 List(whatever).sortWith(_ < _) 或 List(whatever).sorted 那样做,就像我在 Main 中写的那样。我收到以下错误:
pair.scala:14: error: inferred type arguments [Int,String] do not conform to method apply's type parameter bounds [A <: Ordered[A],B <: Ordered[B]]
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
列表中的每一对都是这样:
pair.scala:14: error: type mismatch;
found : Int(1)
required: A
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
还有这个,我不明白:
pair.scala:14: error: diverging implicit expansion for type scala.math.Ordering[Pair[_ >: A with A with A with A <: scala.math.Ordered[_ >: A with A with A with A <: scala.math.Ordered[_ >: A with A with A with A]], _ >: B with B with B with B <: scala.math.Ordered[_ >: B with B with B with B <: scala.math.Ordered[_ >: B with B with B with B]]]]
starting with method $conforms in object Predef
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
我设法让它排序,但只是通过编写知道它们正在排序的类型的排序函数,而不是仅仅知道它们正在排序可排序的类型。正如我所提到的,这些 "aware of the types" 版本是这样的:
case class Pair[A, B](val left: A, val right: B)
{}
object Main extends App
{
val pairs = Array(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b"))
Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x.left, x.right)))
println(pairs.toList)
}
和
case class Pair[A, B](val left: A, val right: B)
{}
object Main extends App
{
val intStringSort = (x: Pair[Int, String], y: Pair[Int, String]) => {
val intCompare = x.left - y.left
if (intCompare == 0)
x.right.compare(y.right) < 0
else
intCompare < 0
}
println(List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sortWith(intStringSort))
}
提前致谢。
使用<%
代替<:
case class Pair[A <% Ordered[A], B <% Ordered[B]]
因为 Int
和 String
都不是 Ordered
。
更新:
但是存在从 Int
到 RichInt
即 Ordered[Int]
和从 String
到 StringOps
即 Ordered[String]
的隐式转换。
<%
表示对象可以隐式转换为定义的类型。
例如,A <% Ordered[A]
for Int
表示存在从 Int
到 Ordered[Int]
的隐式转换,即:
implicit def intWrapper(x: Int) = new runtime.RichInt(x)
in scala.Predef
自动导入。 RichInt
是 Ordered[Int]
。对 String
.
执行类似的步骤
问题出在您的类型范围上,A <: Ordered[A]
和 B <: Ordered[B]
。
Int
和 String
不扩展 Ordered
。但是它们在范围内确实有隐式 Ordering
可用,因此您可以使用隐式边界而不是类型边界。
case class Pair[A, B](left: A, right: B)(implicit a: Ordering[A], b: Ordering[B]) extends Ordered[Pair[A, B]] {
def compare(that: Pair[A, B]) = {
val leftCompare = a.compare(this.left, that.left)
if (leftCompare == 0)
b.compare(this.right, that.right)
else
leftCompare
}
}
scala> List(Pair(1, "a"), Pair(3, "d"), Pair(2, "c"), Pair(2, "b")).sorted
res8: List[Pair[Int,String]] = List(Pair(1,a), Pair(2,b), Pair(2,c), Pair(3,d))
请注意,我在 case class 定义中删除了 val
,因为 case class 字段自动 public。 compare
也不需要 override
因为它需要实现(尽管它可能是某些人的风格偏好)。
我刚开始学习 Scala,为了练习,我决定创建一个 Pair[A, B] class,排序时将首先按 A 排序,然后按 B 排序。我的第一次尝试是这样的:
case class Pair[A <: Ordered[A], B <: Ordered[B]](val left: A, val right: B) extends Ordered[Pair[A, B]]
{
override def compare(that: Pair[A, B]) = {
val leftCompare = this.left.compare(that.left)
if (leftCompare == 0)
this.right.compare(that.right)
else
leftCompare
}
}
object Main extends App
{
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
}
这就是我想要的方式,真的。我想扩展 Ordered 并让它工作,所以我可以像 List(whatever).sortWith(_ < _) 或 List(whatever).sorted 那样做,就像我在 Main 中写的那样。我收到以下错误:
pair.scala:14: error: inferred type arguments [Int,String] do not conform to method apply's type parameter bounds [A <: Ordered[A],B <: Ordered[B]]
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
列表中的每一对都是这样:
pair.scala:14: error: type mismatch;
found : Int(1)
required: A
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
还有这个,我不明白:
pair.scala:14: error: diverging implicit expansion for type scala.math.Ordering[Pair[_ >: A with A with A with A <: scala.math.Ordered[_ >: A with A with A with A <: scala.math.Ordered[_ >: A with A with A with A]], _ >: B with B with B with B <: scala.math.Ordered[_ >: B with B with B with B <: scala.math.Ordered[_ >: B with B with B with B]]]]
starting with method $conforms in object Predef
List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sorted
我设法让它排序,但只是通过编写知道它们正在排序的类型的排序函数,而不是仅仅知道它们正在排序可排序的类型。正如我所提到的,这些 "aware of the types" 版本是这样的:
case class Pair[A, B](val left: A, val right: B)
{}
object Main extends App
{
val pairs = Array(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b"))
Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x.left, x.right)))
println(pairs.toList)
}
和
case class Pair[A, B](val left: A, val right: B)
{}
object Main extends App
{
val intStringSort = (x: Pair[Int, String], y: Pair[Int, String]) => {
val intCompare = x.left - y.left
if (intCompare == 0)
x.right.compare(y.right) < 0
else
intCompare < 0
}
println(List(Pair(1, "a"), Pair(5, "b"), Pair(5, "a"), Pair(1, "b")).sortWith(intStringSort))
}
提前致谢。
使用<%
代替<:
case class Pair[A <% Ordered[A], B <% Ordered[B]]
因为 Int
和 String
都不是 Ordered
。
更新:
但是存在从 Int
到 RichInt
即 Ordered[Int]
和从 String
到 StringOps
即 Ordered[String]
的隐式转换。
<%
表示对象可以隐式转换为定义的类型。
例如,A <% Ordered[A]
for Int
表示存在从 Int
到 Ordered[Int]
的隐式转换,即:
implicit def intWrapper(x: Int) = new runtime.RichInt(x)
in scala.Predef
自动导入。 RichInt
是 Ordered[Int]
。对 String
.
问题出在您的类型范围上,A <: Ordered[A]
和 B <: Ordered[B]
。
Int
和 String
不扩展 Ordered
。但是它们在范围内确实有隐式 Ordering
可用,因此您可以使用隐式边界而不是类型边界。
case class Pair[A, B](left: A, right: B)(implicit a: Ordering[A], b: Ordering[B]) extends Ordered[Pair[A, B]] {
def compare(that: Pair[A, B]) = {
val leftCompare = a.compare(this.left, that.left)
if (leftCompare == 0)
b.compare(this.right, that.right)
else
leftCompare
}
}
scala> List(Pair(1, "a"), Pair(3, "d"), Pair(2, "c"), Pair(2, "b")).sorted
res8: List[Pair[Int,String]] = List(Pair(1,a), Pair(2,b), Pair(2,c), Pair(3,d))
请注意,我在 case class 定义中删除了 val
,因为 case class 字段自动 public。 compare
也不需要 override
因为它需要实现(尽管它可能是某些人的风格偏好)。