如何在不求助于 asInstanceOf 的情况下保留匹配中的原始类型?
How to preserve original type in match without resorting to asInstanceOf?
下面的代码使用的是 ZIO,所以我添加了 scalaz 标签,尽管这可能有点离题。我有一个函数,它采用类型 J
和类型类约束 (Job
):
def execJvm2[J: Job](cmdIn: J): IO[Nothing, Future[RunResult]] = {
type IOJob = IO[Nothing, J]
val cmd0: IOJob = omitted(cmdIn)
val cmd1: IOJob = cmd0.map {
case cmd : OneShot =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd.asInstanceOf[J]
case cmd: Repl =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd.asInstanceOf[J]
case cmd: ExecFile =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd.asInstanceOf[J]
case _ => ???
}
cmd1.map { cmd => poll(cmd.id) }
}
模式匹配中的示例 (OneShot
、Repl
、ExecFile
) 都是 Job
的实例并且在范围内有它们的隐式类型类实例,尽管我我猜这有点离题了。在我看来,这应该在不使用 asInstanceOf
的情况下工作的主要原因是模式匹配中的类型仅从 J
缩小到例如OneShot
,但我认为编译器也会知道它仍然是 J
。
看起来有点差,但我觉得
val cmd1: IOJob = cmd0.map { cmdJ => cmdJ match {
case cmd: OneShot =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmdJ
case cmd: Repl =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmdJ
case cmd: ExecFile =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmdJ
case _ => ???
}}
应该可以。并使用类型擦除作弊,我 认为 这应该可以编译并工作(但请尝试):
val cmd1: IOJob = cmd0.map {
case cmd: OneShot with J @unchecked =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd
case cmd: Repl with J @unchecked =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd
case cmd: ExecFile with J @unchecked =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd
case _ => ???
}
下面的代码使用的是 ZIO,所以我添加了 scalaz 标签,尽管这可能有点离题。我有一个函数,它采用类型 J
和类型类约束 (Job
):
def execJvm2[J: Job](cmdIn: J): IO[Nothing, Future[RunResult]] = {
type IOJob = IO[Nothing, J]
val cmd0: IOJob = omitted(cmdIn)
val cmd1: IOJob = cmd0.map {
case cmd : OneShot =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd.asInstanceOf[J]
case cmd: Repl =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd.asInstanceOf[J]
case cmd: ExecFile =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd.asInstanceOf[J]
case _ => ???
}
cmd1.map { cmd => poll(cmd.id) }
}
模式匹配中的示例 (OneShot
、Repl
、ExecFile
) 都是 Job
的实例并且在范围内有它们的隐式类型类实例,尽管我我猜这有点离题了。在我看来,这应该在不使用 asInstanceOf
的情况下工作的主要原因是模式匹配中的类型仅从 J
缩小到例如OneShot
,但我认为编译器也会知道它仍然是 J
。
看起来有点差,但我觉得
val cmd1: IOJob = cmd0.map { cmdJ => cmdJ match {
case cmd: OneShot =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmdJ
case cmd: Repl =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmdJ
case cmd: ExecFile =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmdJ
case _ => ???
}}
应该可以。并使用类型擦除作弊,我 认为 这应该可以编译并工作(但请尝试):
val cmd1: IOJob = cmd0.map {
case cmd: OneShot with J @unchecked =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd
case cmd: Repl with J @unchecked =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd
case cmd: ExecFile with J @unchecked =>
memStorage(cmd.id) = JobWithResult(cmd, runIO(runInSystem(cmd)))
cmd
case _ => ???
}