The below code is using ZIO, so I've added the scalaz tag, though that may be a bit beside the point. I have a function that takes a type J
with a typeclass constraint (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) }
}
The examples in the pattern match (OneShot
, Repl
, ExecFile
) all are instances of Job
and have their implicit typeclass instances in scope, though I guess that is a bit beside the point. The main reason this should work without using asInstanceOf
, to my thinking, is that the type has only been narrowed down in the pattern match from J
to e.g. OneShot
, but I would think the compiler would know it is still a J
as well.
It looks a bit worse, but I think
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 _ => ???
}}
should work. And cheating with type erasure a bit, I think this should compile and work (but try it):
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 _ => ???
}