如何在不使用asInstanceOf的情况下保留匹配中的原始类型?

时间:2018-08-24 15:08:34

标签: scala scalaz

下面的代码正在使用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) }
  }

模式匹配(OneShotReplExecFile)中的示例都是Job的实例,并且它们的隐式类型类实例在范围内,尽管我猜想有点离题。我认为,在不使用asInstanceOf的情况下应该可以工作的主要原因是,该类型仅在模式匹配中从J缩小为例如OneShot,但我认为编译器也会知道它仍然是J

1 个答案:

答案 0 :(得分:3)

看起来有点糟,但我认为

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 _ => ???
}