2012-02-13 72 views
4

給出的方法foo下面的代碼應該比較操作者明智給定參數barlowerBoundupperBound所有是相同的抽象類型Bar的。如何比較Scala特徵中的有序抽象類型?

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]。將類型Bar定義爲RichInt而不適用,因爲它不符合scala.math.Ordered[RichInt]。我的第三次嘗試將Bar類型定義爲​​,其中Ord被宣佈爲type Ord並將其定義爲FooImpl,因爲Int也不起作用。

一個可能接近的解決方案將如何看起來像?

回答

7

有可能是一個更好的解決方案,但你可以通過在類型移動限制的方法,而不是類型聲明實現這一點:

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 = [email protected] 

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

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

的d這裏isadvantage是性狀可以用無序類型的擴展(儘管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聲明或在泛型類型參數使用它們性狀。

+2

是的,如果OP願意把Foo變成一個抽象類,那麼'Bar'類型的成員可以廢除,Foo的第一行的聲明可以作爲「抽象類Foo [Bar <%Ordered [酒吧]]」。這可能會比在一種方法上強制執行這種關係更好。 – Destin 2012-02-13 01:45:01