scala - 如何比较 Scala 特征中的有序抽象类型?

标签 scala abstract-type

给出方法下面的代码 foo应该按运算符比较给定参数 barlowerBoundupperBound所有都是相同的抽象类型 Bar .

trait Foo {
  type Bar <: Ordered[Bar]
  val lowerBound: Bar
  val upperBound: Bar
  def foo(bar: Bar) = bar >= lowerBound && bar <= upperBound
}

这样的特质Foo可以定义。问题始于下面的具体类 FooImpl .
class FooImpl extends Foo {
  type Bar = Int
  val lowerBound = 0
  val upperBound = 5
}

我明白 scala.Int没有实现什么 scala.runtime.RichInt确实有效 scala.math.Ordered[Int] .定义类型 BarRichInt相反,两者都不起作用,因为它不符合 scala.math.Ordered[RichInt] .我第三次尝试定义类型 BarOrdered[Ord]哪里Ord声明为 type Ord并在 FooImpl 中定义它如 Int也没有用。

一个可能接近的解决方案会是什么样子?

最佳答案

可能有更优雅的解决方案,但您可以通过将类型限制移动到方法而不是类型声明来实现这一点:

trait Foo {
  type Bar
  val lowerBound: Bar
  val upperBound: Bar
  def foo(bar: Bar)(implicit ev: Bar => Ordered[Bar]) = {
    bar >= lowerBound && bar <= upperBound
  }
}

那么你的 FooImpl像你一样工作:
class FooImpl extends Foo {
  type Bar = Int
  val lowerBound = 0
  val upperBound = 5
}

来自 REPL:
scala> new FooImpl()
res0: FooImpl = FooImpl@2dbbec72

scala> res0.foo(3)
res1: Boolean = true

scala> res0.foo(7)
res2: Boolean = false

这里的缺点是可以使用无序类型扩展特征(尽管在这种情况下不能调用 foo):
class A // not Ordered

class BrokenFoo extends Foo {
  type Bar = A
  val lowerBound = new A
  val upperBound = new A
} // compiles

new BrokenFoo().foo(new A) // doesn't compile

或者,您可以将需求保留在类级别(因此阻止任何人创建 BrokenFoo ),如下所示,但 FooImpl必须稍微改变:
trait Foo {
  type Bar
  implicit val baz: Bar => Ordered[Bar]
  val lowerBound: Bar
  val upperBound: Bar
  def foo(bar: Bar) = { bar >= lowerBound && bar <= upperBound }
}

class FooImpl extends Foo {
  type Bar = Int
  val baz = implicitly[Bar => Ordered[Bar]]
  val lowerBound = 0
  val upperBound = 5
}

这个问题感觉就像view or context bounds应该适用,但不幸的是,您似乎无法在 type 中使用它们。声明或在特征的泛型类型参数中。

关于scala - 如何比较 Scala 特征中的有序抽象类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9254027/

相关文章:

Scala groupBy + mapValues + 映射回初始格式。有没有更好的办法

generics - Scala:抽象类型与泛型

scala - Scala:使用具体实例的返回类型实现方法

scala - Scala 是否提供了一种惯用的方式来部分匹配正则表达式以外的字符串?

java - 当我将 scala nature 添加到 Eclipse 中的项目时收到错误

scala - 如何使用 Scala 的 this 类型、抽象类型等来实现 Self 类型?

scala - 在scala中,如何指示编译器实现两个抽象类型的等价?

scala - scala 类定义中这个额外的 private[class]() 是什么意思?

scala - 从 Spark 数据框中提取列值并将其添加到另一个数据框中