Type inference changes in Scala 3

旧巷老猫 提交于 2020-06-11 05:08:27

问题


What changes in type inference will Scala 3 bring? Currently documentation simply states TODO. For example,

Weak conformance

Scala 2.13

scala> val i: Int = 42
val i: Int = 42

scala> val c: Char = 'a'
val c: Char = a

scala> List(i,c)
val res0: List[Int] = List(42, 97)

Scala 3 (dotty 0.24.0-RC1)

scala> val i: Int = 42
val i: Int = 42

scala> val c: Char = 'a'
val c: Char = a

scala> List(i,c)
val res0: List[AnyVal] = List(42, a)

Equality

Scala 2.13

scala> 42 == Some(42)
          ^
       warning: comparing values of types Int and Some[Int] using `==` will always yield false
val res2: Boolean = false

Scala 3

scala> 42 == Some(42)
1 |42 == Some(42)
  |^^^^^^^^^^^^^^
  |Values of types Int and Some[Int] cannot be compared with == or !=

回答1:


So as for your Equality example it is actually caused by the new Multiversal Equality which pretty much means that if you have an Eql[A, B] where A is B then type A can only be compared to things it has an Eql instance for them (of the form Eql[A, C] or Eql[C, A]).

In terms of general type inference for scala 3, the main things are:

  • Union Types: We can now represent union types and expressions like

     if (condition) 1 else "1"
    

    should be of inferred as of type Int | String.

  • Explicit Nulls: One of the new uses for union types is a way to describe nullable types, so for example we could write such a code in Java:

     public String getUser(int id) {
         if (id == 0) {
             return "Admin";
         }
         return null;
     }
    

    And also in scala 2 we could write:

    def getUser(id: Int): String = if (id == 0) return "Admin" else null
    

    But in scala 3 such a method will also have to be declared as of type String | Null to represent its nullability, and will not compile by default in newer versions of scala 3.

    When working with Java it gets more complicated so if you want to know more about it I suggest reading in the link.

  • GADT: Similar to how @functionalInterface works in java we know have GADTs. That means that if you were to have a trait with one unimplemented method:

    trait Fooable {
        def foo(): Unit
    }
    

    You could create an instance of it by passing a lambda with that signature, so in this example:

    val fooable: Fooable = () => print("Fooing")
    

    There are a few more, including Context Functions, Implicit Conversions and Parameter untupling but those are the main ones.




回答2:


Inferred types are now propagated through the remainder of the single parameter list, which means using multiple parameter lists to aid inference might not be necessary.

Scala 2.13

scala> def f[T](i: T, g: T => T) = g(i)
def f[T](i: T, g: T => T): T

scala> f(41, x => x + 1)
             ^
       error: missing parameter type

Scala 3

scala> def f[T](i: T, g: T => T) = g(i)
def f[T](i: T, g: T => T): T

scala> f(41, x => x + 1)
val res0: Int = 42

I guess this change might be related to Allow inter-parameter dependencies #2079



来源:https://stackoverflow.com/questions/62108050/type-inference-changes-in-scala-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!