Marking primitive types with phantom types in Scala

前端 未结 2 615
梦谈多话
梦谈多话 2021-02-10 04:31

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 primi

相关标签:
2条回答
  • 2021-02-10 04:59

    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 讨论(0)
  • 2021-02-10 05:13

    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 */
    
    0 讨论(0)
提交回复
热议问题