【问题标题】:Marking primitive types with phantom types in Scala在 Scala 中用幻像类型标记原始类型
【发布时间】:2011-06-16 21:37:21
【问题描述】:

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

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

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

如果i 是素数,则函数返回值Some(i),否则返回None

是否可以在不装箱原始整数的情况下在 Scala 中实现所述想法?

【问题讨论】:

    标签: scala types static-analysis


    【解决方案1】:

    以下对我有用:

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

    【讨论】:

    • 有趣。我不太明白为什么尽管Intbeeing final,演员阵容仍然有效。我认为这更像是一个错误而不是一个功能。
    • @Landei:我也不确定。在 scala 邮件列表之一上问这个问题是个好问题,其中一位语言设计师可以回答你。
    • @Landei Casts 的意思是“我知道我在做什么,不要试图纠正我。”如果事实证明您不知道自己在做什么,您可能会收到运行时错误,而不是编译时错误。
    • 如果你根据我的回答重新考虑你的最后一行,我会接受这个答案。
    【解决方案2】:

    基于 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)
                          ^
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-05
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多