开发者

Marking primitive types with phantom types in Scala

开发者 https://www.devze.com 2023-03-13 08:18 出处:网络
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 typ

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)
                      ^
0

精彩评论

暂无评论...
验证码 换一张
取 消