在Scala中使用幻像类型标记基本类型

时间:2011-06-15 13:43:38

标签: scala types static-analysis

在Scala中,我可以使用幻像类型的概念(如here所述)来标记类型,并在运行时删除此信息。我想知道是否可以用幻像类型标记原始类型而不用它们装箱。

一个例子可以是一个函数,它允许Int只在它是素数时才通过。签名可能类似于以下内容:

def filterPrime(i: Int): Option[Int with IsPrime]

如果Some(i)为素数或i,则函数返回值None

在没有装箱原始整数的情况下,可以在Scala中实现所提出的想法吗?

2 个答案:

答案 0 :(得分:5)

以下适用于我:

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 */

答案 1 :(得分:4)

在Kim Stebel的回答基础上,我编写了以下内容

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))
    }
}

并使用以下结果在类Test上调用javap

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

}

我们注意到,函数testOddity已被编译为返回未装箱的整数。

以下文件无法编译(这也是我们想要的)。

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)
    }
}

编译器错误

Test.scala:11: error: type mismatch;
 found   : Int(1)
 required: Int with IsOdd
        acceptOdd(1)
                      ^