如何在不诉诸asInstanceOf的情况下保留匹配的原始类型?



下面的代码使用的是ZIO,所以我添加了scalaz标签,尽管这可能有点偏离重点。我有一个函数,它采用具有类型类约束(Job(的类型J

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) }
}

模式匹配中的示例(OneShotReplExecFile(都是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 _ => ???
}

最新更新