gpt4 book ai didi

scala - 匹配/大小写上的路径相关打字

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

sealed trait Desc {
type T
}

trait Dataset[A] {
def toDS[A] = new Dataset[A] {}
}
trait DataFrame {}


sealed trait DFDesc extends Desc {
type T = Dummy
}

sealed trait DSDesc[A] extends Desc {
type T = A
}

trait JobConstruction {
def apply(desc: Desc): Job[desc.T]
}

sealed trait Job[DescType] {
def description: Desc { type T = DescType }
}

abstract class DSJob[V] extends Job[V] {
def result(con: JobConstruction): Dataset[V]
}

abstract class DFJob extends Job[Dummy] {
def result(con: JobConstruction): DataFrame
}

trait Dummy {}

case class SampleDFDesc() extends DFDesc
case class SampleDFJob(description: SampleDFDesc) extends DFJob {
override def result(con: JobConstruction) = new DataFrame {}
}
case class SampleDSDesc() extends DSDesc[Int]
case class SampleDSJob(description: SampleDSDesc) extends DSJob[Int] {
override def result(con: JobConstruction) = new Dataset[Int] {}
}

object Main {
val sampleConst = new JobConstruction {
override def apply(desc: Desc): Job[desc.T] = desc match {
case desc2: SampleDFDesc => SampleDFJob(desc2)
case desc2: SampleDSDesc => SampleDSJob(desc2)
}
}
}

无法编译
/tmp/sample.scala:73: error: type mismatch;
found : this.SampleDFJob
required: this.Job[desc.T]
case desc2: SampleDFDesc => SampleDFJob(desc2)
^
/tmp/sample.scala:74: error: type mismatch;
found : this.SampleDSJob
required: this.Job[desc.T]
case desc2: SampleDSDesc => SampleDSJob(desc2)

编辑:

我想让它以某种方式工作:
case class SampleDepDesc(df: SampleDFDesc) extends DSDesc[Int]
case class SampleDepJob(description: SampleDepDesc) extends DSJob[Int] {
override def result(con: JobConstruction): Dataset[Int] = con(description.df).result(con).toDS[Int]
}

最佳答案

问题分析

如果你写 sampleConst,错误会以更有趣的方式表达出来。像这样:

object Main {
val sampleConst = new JobConstruction {
override def apply(desc: Desc): Job[desc.T] = {
val result = desc match {
case desc2: SampleDFDesc => SampleDFJob(desc2)
case desc2: SampleDSDesc => SampleDSJob(desc2)
}
result
}
}

错误信息变为:
type mismatch;
found : Product with Serializable with main.Job[_ >: main.Dummy with Int]{def description: Product with Serializable with main.Desc{type T >: main.Dummy with Int}}
required: main.Job[desc.T]
Note: Any >: desc.T (and Product with Serializable with main.Job[_ >: main.Dummy with Int]{def description: Product with Serializable with main.Desc{type T >: main.Dummy with Int}} <: main.Job[_ >: main.Dummy with Int]), but trait Job is invariant in type DescType. You may wish to define DescType as -DescType instead. (SLS 4.5)

这条消息很难阅读。原因似乎是逆变的问题,如第四行所述,但让我们首先尝试使此错误消息可读。

这条消息这么长的原因是 Scala 做了很多体操,以便理解所有这些类型转换和继承。我们将(暂时)将类型层次结构展平一点,以便更清楚地了解这一切。

在这里,中介类 SampleDFJob , SampleDSJob , SampleDFDescSampleDSDesc已被删除:
sealed trait Desc {
type T
}

sealed trait DFDesc extends Desc {
type T = Dummy
}

sealed trait DSDesc[A] extends Desc {
type T = A
}

trait JobConstruction {
def apply(desc: Desc): Job[desc.T]
}

sealed trait Job[DescType] {
def description: Desc { type T = DescType }
}

class DSJob[V] extends Job[V]

class DFJob extends Job[Dummy]

trait Dummy {}

object Main {
val sampleConst = new JobConstruction {
override def apply(desc: Desc): Job[desc.T] = {
val result = desc match {
case desc2: DFDesc => new DFJob
case desc2: DSDesc[Int] => new DSJob[Int]
}
result
}
}
}

错误信息现在是:
type mismatch;
found : main.Job[_1] where type _1 >: main.Dummy with Int
required: main.Job[desc.T]

问题似乎是 Scala 无法转换 main.Job[_ >: main.Dummy with Int]进入 desc.T .

注:为什么是这种奇怪的类型?那么,泛型类型 result取决于模式匹配的情况(在第一种情况下,我们有一个 Dummy,在第二种情况下,我们有一个 Int)。由于 Scala 是静态类型的(至少在编译期间),它会尝试组成一个返回类型,它是所有可能类型的“公分母”(或者更确切地说,父类型)。它找到的最好的东西是 _ >: main.Dummy with Int ,它是“在模式匹配中找到的任何类型的父类型的任何类型”( main.DummyInt )。

为什么它不起作用

我认为这种类型不能被转换为 desc.T 的原因Scala 无法在编译时确认返回的类型始终是 (因为 DescType 是不变的)如 Job[desc.T] .确实, desc.T来自 SampleDFDesc.TSampleDSDesc.T ,而返回类型将为 DescType , 并不能保证这两种类型是相同的(如果 SampleDSJob 扩展 DSJob[String] 呢?)

解决方案

我不认为可以完全按照您尝试的方式进行编码,但是您可以尝试...回避问题:

如果您确定每个 case 的返回类型将始终与 desc.T 的类型相同,然后您可以使用 asInstanceOf 指定显式转换,像这样:
object Main {
val sampleConst = new JobConstruction {
override def apply(desc: Desc): Job[desc.T] = (desc match {
case desc2: SampleDFDesc => SampleDFJob(desc2)
case desc2: SampleDSDesc => SampleDSJob(desc2)
}).asInstanceOf[Job[desc.T]]
}
}

当然,这不是类型安全的。

或者,如果您可以设法编写 Job类使 DescType可以逆变( -DescType ),你可以写成 Job.apply方法改为具有以下签名:
def apply(desc: Desc): Job[_ <: desc.T]

关于scala - 匹配/大小写上的路径相关打字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34907973/

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