【问题标题】:Type inference changes in Scala 3Scala 3 中的类型推断变化
【发布时间】:2020-09-18 07:51:03
【问题描述】:

Scala 3 会给类型推断带来哪些变化? 当前文档仅声明 TODO。例如,

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)

平等

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

斯卡拉 3

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

【问题讨论】:

标签: scala type-inference dotty scala-3


【解决方案1】:

至于您的Equality 示例,它实际上是由新的Multiversal Equality 引起的,这几乎意味着如果您有一个Eql[A, B],其中A 是B,那么类型A 只能与它具有@ 的东西进行比较他们的 987654329@ 实例(形式为 Eql[A, C]Eql[C, A])。

就 scala 3 的一般类型推断而言,主要是:

  • Union Types:我们现在可以表示联合类型和表达式,如

     if (condition) 1 else "1"
    

    应该推断为Int | String类型。

  • Explicit Nulls:联合类型的新用途之一是描述可空类型,因此例如我们可以用 Java 编写这样的代码:

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

    在 scala 2 中我们也可以这样写:

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

    但在 scala 3 中,此类方法也必须声明为 String | Null 类型以表示其可空性,并且默认情况下不会在新版本的 scala 3 中编译。

    使用 Java 时会变得更加复杂,因此如果您想了解更多信息,我建议您阅读链接。

  • GADT:类似于@functionalInterface 在 java 中的工作方式,我们知道有 GADT。 这意味着,如果您要具有一个未实现方法的特征:

    trait Fooable {
        def foo(): Unit
    }
    

    您可以通过传递带有该签名的 lambda 来创建它的实例,因此在此示例中:

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

    还有一些,包括Context FunctionsImplicit ConversionsParameter untupling,但这些是主要的。

【讨论】:

  • 关于 GADT 要点 - Fooable 似乎是 SAM 已经有一段时间了。 SAM 与 GADT 有什么关系?
  • 对不起,你是对的我的意思是SAM,很抱歉混淆了名字,我实际上是不小心合并了两个点。关于 GADT,我的意思是 GADT 成员(特别是枚举)在实例化时被推断为枚举类型,而不是它们的实际类型。因此,例如 enum Bool{ case True case False } 将 Bool.True 推断为 Bool 类型而不是 Bool.True,即使这是它的基础类型。关于 SAM 的事实是它们现在被推断为 java 类型(不再是 new Runnable() { def run() .. }
【解决方案2】:

推断类型现在通过单个参数列表的其余部分传播,这意味着可能不需要使用多个参数列表来辅助推断。

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

斯卡拉 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

我猜这个变化可能和Allow inter-parameter dependencies #2079有关


当类型参数没有以术语出现时更好的推理

Scala 2.13

scala> def f[F <: List[A], A](as: F) = as
def f[F <: List[A], A](as: F): F

scala> f(List(42))
       ^
       error: inferred type arguments [List[Int],Nothing] do not conform to method f's type parameter bounds [F <: List[A],A]
             ^
       error: type mismatch;
        found   : List[Int]
        required: F

斯卡拉 3

scala> def f[F <: List[A], A](as: F) = as                                                                                                                
def f[F <: List[A], A](as: F): F

scala> f(List(42))                                                                                                                                       
val res0: List[Int] = List(42)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多