简体   繁体   English

如何比较Scala特征中的Ordered抽象类型?

[英]How to compare Ordered abstract type in Scala trait?

Given the code below the method foo should compare operator-wise a given parameter bar with the lowerBound and upperBound all being of the same abstract type Bar . 给定下面的代码,方法foo应该比较操作符给定的参数barlowerBoundupperBound都是相同的抽象类型Bar

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

This way the trait Foo can be defined. 这样就可以定义特征Foo The problems start with the below concrete class FooImpl . 问题从下面的具体类FooImpl

class FooImpl extends Foo {
  type Bar = Int
  val lowerBound = 0
  val upperBound = 5
}

I understand that scala.Int isn't implementing what scala.runtime.RichInt does, effectively scala.math.Ordered[Int] . 我知道scala.Int没有实现scala.runtime.RichInt功能,实际上是scala.math.Ordered[Int] Defining type Bar as RichInt instead neither works as it does not conform to scala.math.Ordered[RichInt] . 将类型Bar定义为RichInt则不起作用,因为它不符合scala.math.Ordered[RichInt] My third attempt to define type Bar as Ordered[Ord] where Ord is declared as type Ord and defining it in FooImpl as Int also did not work. 我第三次尝试将类型Bar定义为Ordered[Ord] ,其中Ord被声明为type Ord并在FooImpl其定义为Int也不起作用。

How would a possibly close solution look like? 一个可能接近的解决方案怎么样?

There may be a more elegant solution, but you can achieve this by moving the restriction on the type to the method, rather than the type declaration: 可能有一个更优雅的解决方案,但您可以通过将类型的限制移动到方法而不是类型声明来实现此目的:

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

Then your FooImpl works as you have it: 然后你的FooImpl就像你拥有它一样:

class FooImpl extends Foo {
  type Bar = Int
  val lowerBound = 0
  val upperBound = 5
}

From the REPL: 来自REPL:

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

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

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

The disadvantage here is that the trait can be extended with unordered types (although foo can't be called in that case): 这里的缺点是特性可以用无序类型扩展(尽管在这种情况下不能调用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

Alternatively, you can keep the requirement at the class level (and therefore stop anyone creating a BrokenFoo ) as follows, but FooImpl has to change slightly: 或者,您可以将需求保持在类级别(因此阻止任何创建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
}

This problem feels like view or context bounds should be applicable, but unfortunately it doesn't seem like you can use them either in type declarations or in generic type parameters on traits. 这个问题感觉像视图或上下文边界应该适用,但不幸的是,你似乎不能在type声明或特征上的泛型类型参数中使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM