Маркировка примитивных типов фантомными типами в Scala - PullRequest
5 голосов
/ 15 июня 2011

В Scala я могу использовать концепцию фантомных типов (как описано, например, здесь ), чтобы отмечать типы и стирать эту информацию во время выполнения.Интересно, можно ли пометить примитивные типы фантомными типами, не помещая их в штучную упаковку?

Примером может служить функция, которая позволяет Int проходить только в случае простого числа.Сигнатура может выглядеть примерно так:

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

Функция возвращает значение Some(i), если i простое или None else.

Возможна ли заявленная идея дляреализовать в Scala без бокса примитивное целое число?

Ответы [ 2 ]

5 голосов
/ 15 июня 2011

У меня работает следующее:

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 */
4 голосов
/ 15 июня 2011

Опираясь на ответ Ким Стебель, я скомпилировал следующее

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

и вызвал javap для класса Test со следующим результатом

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