4

显然Range有一个方法可以检查它是否包含任何类型的值。我知道它来自SeqLike,但会导致一些问题。

例如,我匹配 joda.DateTime 的小时数:

DateTime.now match {
    case d if 0 to 12 contains d.hourOfDay() => ...

这里 d.hourOfDay() 返回 DateTime.Property,而不是 Int,但代码仍然可以编译,因为contains(elem: Any). 有没有办法在编译时检查此类调用?

4

3 回答 3

7

您可以将 Scalaz 的类型安全 equals ( ===) 与exists方法 on结合使用TraversableOnce

scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> 1 to 5 exists { _ === 2 }
res1: Boolean = true

scala> 1 to 5 exists { _ === "Hullo" }
<console>:14: error: type mismatch;
 found   : java.lang.String("Hullo")
 required: Int
       1 to 5 exists { _ === "Hullo" }
                             ^
于 2011-09-12T10:36:18.747 回答
6

您可以pimp Range添加类型安全的 contains 方法:

class SafeRange( range: Range ) {
  def safeContains( i: Int ) = range contains i
}

object SafeRange {
  implicit def safer( range: Range ) = new SafeRange( range )
}

导入隐式并调用safeContains任何范围实例:

scala> import SafeRange._
import SafeRange._

scala> (0 until 10) safeContains 3
res2: Boolean = true

scala> (0 until 10) safeContains 100
res3: Boolean = false

scala> (0 until 10) safeContains "foo"
<console>:18: error: type mismatch;
 found   : java.lang.String("foo")
 required: Int
          (0 until 10) safeContains
于 2011-09-12T07:58:26.060 回答
3

根据Range 的 scaladocs,您似乎没有更好的 Range 方法可以使用。你的选择似乎是

使用显式类型签名:

 case d if 0 to 12 contains (d.hourOfDay(): Int) => ...

制作自己的方法:

 def containsInt(r: Range, i: Int) = ...

这似乎是 Javaequals作为前泛型的保留,并且只是这一事实给 Scala 带来的不便之一。

于 2011-09-12T07:53:27.917 回答