What is the concept of “weak conformance” in Scala?

后端 未结 3 1505
伪装坚强ぢ
伪装坚强ぢ 2020-12-24 12:49

I just recently encountered the term \"Weak Conformance\" (in Stack Overflow user retronym\'s answer to How to set up implicit conversion to allow arithmetic between num

3条回答
  •  Happy的楠姐
    2020-12-24 13:02

    3.5.3 Weak Conformance In some situations Scala uses a more general conformance relation. A type S weakly conforms to a type T , written S <:w T , if S <: T or both S and T are primitive number types and S precedes T in the following ordering.

    • Byte <:w Short
    • Byte <:w Character
    • Short <:w Int
    • Int <:w Long
    • Long <:w Float
    • Float <:w Double

    A weak least upper bound is a least upper bound with respect to weak conformance.

    Where is this used? For one thing, it determines the type of if expressions:

    The type of the conditional expression is the weak least upper bound (§3.5.3) of the types of e2 and e3

    In Scala 2.7.x, this would by of type AnyVal, the least uppper bound of Int and Double. In 2.8.x, it types as Double.

    scala> if (true) 1 else 1d
    res0: Double = 1.0
    

    Similarly:

    scala> try { 1 } catch { case _ => 1.0 }
    res2: Double = 1.0
    
    scala> (new {}: Any) match { case 1 => 1; case _ => 1.0 }
    res6: Double = 1.0
    
    scala> def pf[R](pf: PartialFunction[Any, R]): PartialFunction[Any, R] = pf
    pf: [R](pf: PartialFunction[Any,R])PartialFunction[Any,R]
    
    scala> pf { case 1 => 1; case _ => 1d }
    res4: PartialFunction[Any,Double] = 
    

    Another place it is used is in type inference:

    scala> def foo[A](a1: A, a2: A): A = a1
    foo: [A](a1: A,a2: A)A
    
    scala> foo(1, 1d)
    res8: Double = 1.0
    
    scala> def foos[A](as: A*): A = as.head
    foos: [A](as: A*)A
    
    scala> foos(1, 1d)
    res9: Double = 1.0
    

    And also for simple numeric widening:

    Numeric Widening. If e has a primitive number type which weakly conforms (§3.5.3) to the expected type, it is widened to the expected type using one of the 6.26 Implicit Conversions 97 numeric conversion methods toShort, toChar, toInt, toLong, toFloat, toDouble defined in §12.2.1. expected type is a primitive numeric type Byte, Short or Char, and the expression e is an integer literal fitting in the range of that type, it is converted to the same literal in that type.

    scala> 1: Double
    res10: Double = 1.0
    

    UPDATE

    As pointed out by Daniel, the spec is wrong about which types have weak conformance. Let's ask the compiler itself:

    scala> :power
    ** Power User mode enabled - BEEP BOOP      **
    ** scala.tools.nsc._ has been imported      **
    ** New vals! Try repl, global, power        **
    ** New cmds! :help to discover them         **
    ** New defs! Type power. to reveal     **
    
    scala> settings.maxPrintString = 10000
    
    
    scala> import global.definitions._
    import global.definitions._
    
    scala> (for{c1 <- ScalaValueClasses;
          c2 <- ScalaValueClasses
          isNSC = isNumericSubClass(c1, c2)
          if isNSC
      } yield ("isNumericSubClass (%s, %s) = %b" format (c1, c2, isNSC))).mkString("\n")
    
    
    res5: String =
    isNumericSubClass (class Byte, class Byte) = true
    isNumericSubClass (class Byte, class Short) = true
    isNumericSubClass (class Byte, class Int) = true
    isNumericSubClass (class Byte, class Long) = true
    isNumericSubClass (class Byte, class Float) = true
    isNumericSubClass (class Byte, class Double) = true
    isNumericSubClass (class Short, class Short) = true
    isNumericSubClass (class Short, class Int) = true
    isNumericSubClass (class Short, class Long) = true
    isNumericSubClass (class Short, class Float) = true
    isNumericSubClass (class Short, class Double) = true
    isNumericSubClass (class Int, class Int) = true
    isNumericSubClass (class Int, class Long) = true
    isNumericSubClass (class Int, class Float) = true
    isNumericSubClass (class Int, class Double) = true
    isNumericSubClass (class Long, class Long) = true
    isNumericSubClass (class Long, class Float) = true
    isNumericSubClass (class Long, class Double) = true
    isNumericSubClass (class Char, class Int) = true
    isNumericSubClass (class Char, class Long) = true
    isNumericSubClass (class Char, class Char) = true
    isNumericSubClass (class Char, class Float) = true
    isNumericSubClass (class Char, class Double) = true
    isNumericSubClass (class Float, class Float) = true
    isNumericSubClass (class Float, class Double) = true
    isNumericSubClass (class Double, class Double) = true
    

提交回复
热议问题