我看到了两个潜在的解决方案:
首先你可以看看Unboxed Type Tags。它们允许在编译时附加一个类型,而不必将整数装箱。编译器将强制在需要时使用它们,但在运行时检查值。
从引用的文章中,您可以编写如下内容:
type Tagged[U] = { type Tag = U }
type @@[T, U] = T with Tagged[U]
trait Positive
trait One2Three
type PositiveInt = Int @@ Positive
type SmallInt = Int @@ One2Three
//Builds a small int
def small(i: Int): SmallInt = {
require( i > 0 && i < 4, "should be between 1 and 3" )
i.asInstanceOf[SmallInt]
}
//Builds a positive int
def positive( i: Int): PositiveInt = {
require( i >= 0, "should be positive" )
i.asInstanceOf[PositiveInt]
}
//Example usage in methods
def mul( i: SmallInt, j: PositiveInt ): PositiveInt = positive(i*j)
然后在 REPL 中:
scala> mul( small(2), positive(4) )
res1: PositiveInt = 8
scala> mul( small(4), positive(2) ) //RUNTIME ERROR
java.lang.IllegalArgumentException: should be between 1 and 3
scala> mul( 2, positive(2) ) //COMPILE TIME ERROR
<console>:16: error: type mismatch;
found : Int(2)
required: SmallInt
mul( 2, positive(2) )
^
第二种解决方案可能是为 Scala 2.10 提出的值类。您可以阅读SIP-15以了解如何使用它们。