gpt4 book ai didi

具有存在类型 : `map{ case t => ... }` works, `map{ t => ... }` 的 Scala 列表不是吗?

转载 作者:行者123 更新时间:2023-12-01 03:14:18 27 4
gpt4 key购买 nike

假设我们已经定义了一个存在类型:

type T = (X => X, X) forSome { type X }

然后定义了一个 List[T] 类型的列表:
val list = List[T](
((x: Int) => x * x, 42),
((_: String).toUpperCase, "foo")
)

众所周知 [ 1 ], [ 2 ] 以下尝试 map不起作用:
list.map{ x => x._1(x._2) }

但是,为什么以下工作?:
list.map{ case x => x._1(x._2) }

请注意,两个链接问题的答案都假定模式匹配中需要一个类型变量,但它也可以在没有类型变量的情况下工作。问题的重点更多是为什么 { case x => ... }工作?。

最佳答案

(我自己试图回答这个问题;应该不会太错,但可能有点肤浅。)

首先,观察

list.map{ x => x._1(x._2) }
list.map{ case x => x._1(x._2) }

本质上是一样的
list map f1
list map f2


val f1: T => Any = t => t._1(t._2)
val f2: T => Any = _ match {
case q => q._1(q._2)
}

确实,编译 f1失败,而 f2成功。

我们可以看到为什么编译 f1必须失败:
  • t类型为 (X => X, X) forSome { type X }
  • 因此,第一个分量 t._1推断具有类型 (X => X) forSome { type X } .
  • 同样,第二个分量 t._2推断具有类型 X forSome { type X } ,这只是 Any .
  • 我们不能申请 (X => X) forSome { type X }Any ,因为它实际上可能是 (SuperSpecialType => SuperSpecialType)一些 SuperSpecialType .

  • 因此,编译 f1应该失败,它确实失败了。

    看看为什么 f2编译成功,可以查看类型检查器的输出。如果我们将其保存为 someFile.scala :
    class O {
    type T = (X => X, X) forSome { type X }

    def f2: T => Any = t => t match {
    case q => q._1(q._2)
    }

    def f2_explicit_func_arg: T => Any = t => t match {
    case q => {
    val f = q._1
    val x = q._2
    f(x)
    }
    }
    }

    然后生成类型检查器的输出
    $ scalac -Xprint:typer someFile.scala 

    我们基本上得到(去除了一些噪音):
    class O extends scala.AnyRef {
    type T = (X => X, X) forSome { type X };
    def f2: O.this.T => Any = ((t: O.this.T) => t match {
    case (q @ _) => q._1.apply(q._2)
    });
    def f2_explicit_func_arg: O.this.T => Any = ((t: O.this.T) => t match {
    case (q @ _) => {
    val f: X => X = q._1;
    val x: X = q._2;
    f.apply(x)
    }
    })
    }

    第二个 f2_explicit_func_arg版本(相当于 f2)比较短的原版 f2 更有启发性-版本。在 f2_explicit_func_arg 的脱糖和类型检查代码中,我们看到类型 X奇迹般地重新出现,类型检查器确实推断:
    f: X => X
    x: X

    以便 f(x)确实有效。

    在使用显式命名的类型变量的更明显的解决方法中,我们手动执行编译器在这种情况下为我们所做的工作。

    我们也可以这样写:
    type TypeCons[X] = (X => X, X)
    list.map{ case t: TypeCons[x] => t._1(t._2) }

    或者更明确地说:
    list.map{ case t: TypeCons[x] => {
    val func: x => x = t._1
    val arg: x = t._2
    func(arg)
    }}

    并且这两个版本的编译原因与 f2 非常相似.

    关于具有存在类型 : `map{ case t => ... }` works, `map{ t => ... }` 的 Scala 列表不是吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49712171/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com