显然Range
有一个方法可以检查它是否包含Any类型的值。我知道它来自SeqLike
,但会导致一些问题。
例如,我从joda.DateTime:
匹配小时DateTime.now match {
case d if 0 to 12 contains d.hourOfDay() => ...
这里d.hourOfDay()返回DateTime.Property,而不是Int,但代码仍在编译,因为contains(elem: Any)
。有没有办法在编译时检查这样的调用?
答案 0 :(得分:7)
您可以在===
上将Scalaz的类型安全等号(exists
)与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" }
^
答案 1 :(得分:6)
您可以pimp Range
添加类型更安全的包含方法:
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
答案 2 :(得分:3)
基于the scaladocs for Range,看起来没有更好的Range方法可以使用。您的选择似乎是
使用显式类型签名:
case d if 0 to 12 contains (d.hourOfDay(): Int) => ...
制作自己的方法:
def containsInt(r: Range, i: Int) = ...
这似乎是Java equals
作为预先仿制药的延续,这只是Scala带来的不便之处。