Scala:有没有一种方法可以将类型别名视为不同于它们所别名的类型?

Scala:有没有一种方法可以将类型别名视为不同于它们所别名的类型?,scala,casting,implicit-conversion,typechecking,Scala,Casting,Implicit Conversion,Typechecking,给出以下示例:我希望截断字符串以满足某些长度约束,例如与SQL类型的兼容性 type varchar8 = String implicit def str2Varchar8(str: String): varchar8 = str.take(8) val a: varchar8 = "abcdefghi" // wanted: "abcdefgh", actual result: a: varchar8 = abcdefghi 编译器似乎没有区分这两种类型 给定一个类型别名type a=

给出以下示例:我希望截断字符串以满足某些长度约束,例如与SQL类型的兼容性

type varchar8 = String

implicit def str2Varchar8(str: String): varchar8 = str.take(8)

val a: varchar8 = "abcdefghi"

// wanted: "abcdefgh", actual result:
a: varchar8 = abcdefghi
编译器似乎没有区分这两种类型

给定一个类型别名
type a=String
,我试图实现的是:

  • 避免运行时分配(即包装类)
  • 仅当从
    String
    映射到类型别名
    A
    时才应用断言/转换的能力。i、 e.当直接使用类型别名
    A
    作为输入时,避免进一步的断言/转换
  • 验证示例:

    type NotNullA = A
    
    def method(a: A) = if(a != null)
        _method(a: NotNullA) // explicit typing
      else
        ???
    
    // "a" at runtime is a String but we consider it validated, instead relying on the type system
    protected def _method(a: NotNullA) = ???
    protected def _otherMethod(a: NotNullA) = ???
    
    是否有一种方法可以将类型别名视为与其别名的类型分开,从而使它们之间的隐式转换和类型检查成为可能?是否有其他编码/技术可以完成这项工作

    旁白:我似乎记得有一点,这两个是分开的,类型和别名是不同的(与类型arity问题无关)。我以前的代码类似于:

    type FieldAType = Int
    
    // and in a different class
    def method(a: FieldAType) = ???
    
    val b: FieldAType = 1
    method(b) // worked
    
    val c: Int = 1
    method(c) // compiler error
    method(c: FieldAType) // worked
    

    但是,我无法重现此问题(可能是因为较旧的Scala版本-目前使用2.11.8)

    据我所知,这是不可能的。别名只是一个附加名称。纯粹为了可读性


    但是,您可以使用。它们是完全不同的类型,因此您可以在代码中以不同的方式处理它们。但大多数情况下,编译器能够避免实际分配包装器对象-链接页面中有更多关于此异常的信息。

    我建议您查看库

    • 无运行时开销

    • 保护您的类型的可靠方法

    只需添加导入并定义标记的类型:

    import com.softwaremill.tagging._
    
    type EvenTag
    type EvenInt = Int @@ EvenTag
    
    object EvenInt {
      def fromInt(i: Int): Option[EvenInt] =
        if (i % 2 == 0) Some(i.taggedWith[EvenTag]) else None
    }
    
    def printEvenInt(evenInt: EvenInt): Unit = println(evenInt)
    
    EvenInt.fromInt(2).foreach(printEvenInt)
    
    val evenInt: EvenInt = 2 // Doesn't compile
    printEvenInt(2) // Doesn't compile
    
    我们如何破解它

    val evenInt: EvenInt = 1.taggedWith[EvenTag]
    

    享受吧

    Scala 3中可能会实现一个功能:
    不透明类型
    s

    它们从字面上解决了您描述的问题:能够根据名称而不是真正的底层类型来区分类型别名和普通类型


    请看一看。

    我设想在受保护代码中使用的用例,并确保没有类型错误/bug。似乎它还可以支持多态性:“当U是V的子类型时,仅当需要T@@V类型的实例时,才可以使用x:T@@U(U有一长串异常和限制,但我喜欢简单:),类型安全性、转换支持等可能会超过潜在的对象分配成本。