Marking primitive types with phantom types in Scala
In Scala I can use the concept of phantom types (as described e.g. here) to mark types and have 开发者_运维问答this information erased at runtime. I wonder whether it is possible to mark primitive types with phantom types without having them boxed.
An example could be a function that lets an Int only pass if it is a prime. The signature might look similar to the following:
def filterPrime(i: Int): Option[Int with IsPrime]
The function returns the value Some(i)
if i
is prime or None
else.
Is the stated idea possible to implement in Scala without boxing the primitive integer?
The following works for me:
trait IsPrime
val x = 5.asInstanceOf[Int with IsPrime]
val y:Int = x
val z:Int with IsPrime = 6 /* this line causes a compile error
which is what you want */
Building on Kim Stebel's answer I've compiled the following
trait IsOdd
object Test{
def testOddity(i: Int): Int with IsOdd =
if( i % 2 == 0) throw new RuntimeException
else i.asInstanceOf[Int with IsOdd]
def main(args: Array[String]) {
println(testOddity(1))
}
}
and invoked javap on the class Test
with the following result
Compiled from "Test.scala"
public final class Test extends java.lang.Object{
public static final void main(java.lang.String[]);
Code:
0: getstatic #11; //Field Test$.MODULE$:LTest$;
3: aload_0
4: invokevirtual #13; //Method Test$.main:([Ljava/lang/String;)V
7: return
public static final int testOddity(int);
Code:
0: getstatic #11; //Field Test$.MODULE$:LTest$;
3: iload_0
4: invokevirtual #17; //Method Test$.testOddity:(I)I
7: ireturn
}
We notice, that the function testOddity
has been compiled to return an unboxed integer.
And the following file doesn't compile (which is also what we wanted).
trait IsOdd
object Test{
def testOddity(i: Int): Int with IsOdd =
if( i % 2 == 0) throw new RuntimeException
else i.asInstanceOf[Int with IsOdd]
def acceptOdd(i: Int with IsOdd) { println("got it") }
def main(args: Array[String]) {
println(testOddity(1))
acceptOdd(1)
}
}
compiler error
Test.scala:11: error: type mismatch;
found : Int(1)
required: Int with IsOdd
acceptOdd(1)
^
精彩评论