代码之家  ›  专栏  ›  技术社区  ›  Than21

scala确保块中的隐式转换失败

  •  2
  • Than21  · 技术社区  · 8 年前

    我使用scalac 2.12.1编译以下程序,没有任何选项:

    import scala.language.implicitConversions
    
    case class Int32(v : Int) {
    }
    case class Int64(v : BigInt) {
        def > (that : Int64) = this.v > that.v
        def <= (that : Int64) = this.v <= that.v
    }
    object implicits {
        implicit def int32Toint64(input : Int32) = Int64(BigInt(input.v))
    }
    import implicits._
    
    class myTest {
        def max(x: Int64, y: Int32) : Int64 = {
            if (x > y)
                x
            else
                y  // If this is replaced with int32Toint64(y) it works !
        } ensuring(res => x <= res && y <= res) // <= error: missing parameter type for 'res'
    }
    

    上述程序未能编译,出现注释中所示的错误。 我的期望是隐式转换 int32Toint64 将自动生效。注意,如果我显式地进行转换,即如果我替换 y 具有 int32Toint64(y) ,则程序编译成功。所以我很困惑。为什么我会看到这种行为?有没有办法在没有显式转换的情况下防止此错误?

    谢谢

    1 回复  |  直到 8 年前
        1
  •  2
  •   Andrey Tyukin    8 年前

    这项工作:

    class myTest {
        def max(x: Int64, y: Int32) : Int64 = {
            if (x > y)
                x
            else
                (y : Int64)
        } ensuring(res => x <= res && y <= res)
    }
    

    这也适用于:

    class myTest {
        def max(x: Int64, y: Int32) : Int64 = ({
            if (x > y)
                x
            else
                y
        }: Int64) ensuring(res => x <= res && y <= res)
    }
    

    这显然行不通:

    class myTest {
        def max(x: Int64, y: Int32) : Int64 = {
            if (x > y)
                x
            else
                y
        } ensuring((res: Int64) => x <= res && y <= res)
    }
    

    为什么?单独查看此表达式:

        {
            if (x > y)
                x
            else
                y
        }
    

    如果没有显式地指定类型,编译器可以从中派生什么?它将派生出如下内容 Serializable ,甚至 AnyRef . 它还能做什么?打字机以非常直接的方式工作。它只是查看一个表达式,尝试派生它的最精确类型,如果没有从外部指定类型,它不会尝试隐式转换任何内容。而且它不会开始在代码的偏远角落搜索其他类型提示。在这种情况下, ensuring ( ... ) 既不是此表达式的一部分,也不允许显式返回类型归属 : Int64 = 涓涓细流。

    我想,要理解为什么这一点显而易见,最好的方法是为简单类型的lambda演算编写一个小的类型检查器:它非常简单,但在类似的情况下,它已经表现出完全相同的行为。