How to get around erased types in pattern match?
Example code:
trait RouteRequest
trait RouteResponse
case class Request() extends RouteRequest
case class Response(name: String) extends RouteResponse
type Disparcher[Req <: RouteRequest, Resp <: RouteResponse] = Req => Resp
type DisparcherAsync[Req <: RouteRequest, Resp <: RouteResponse] = (Req, Resp => Unit) => Unit
trait ControllerBase
trait Controller1[Req <: RouteRequest, Resp <: RouteResponse] extends ControllerBase:
def dispatch(r: Req): Resp
trait Controller2[Req <: RouteRequest, Resp <: RouteResponse] extends ControllerBase:
def dispatch(r: Req): Resp
class ControllerA extends Controller1[Request, Response]:
def dispatch(r: Request): Response = Response("Controller A")
class ControllerB extends Controller2[Request, Response]:
def dispatch(r: Request): Response = Response("Controller B")
type Handlers[Req <: RouteRequest, Resp <: RouteResponse] =
Controller1[Req, Resp] | Controller2[Req, Resp] | Disparcher[Req, Resp] | DisparcherAsync[Req, Resp]
def handle[Req <: RouteRequest, Resp <: RouteResponse](c: Handlers[Req, Resp]): Unit =
val req = Request().asInstanceOf[Req]
c match
case c1: Controller1[_, _] =>
val ct = c1.asInstanceOf[Controller1[Req, Resp]]
println(ct.dispatch(req))
case c1: Controller2[_, _] =>
val ct = c1.asInstanceOf[Controller2[Req, Resp]]
println(ct.dispatch(req))
case c1: Disparcher[_, _] =>
val cb = c1.asInstanceOf[Disparcher[Req, Resp]]
println(cb(req))
case c1: DisparcherAsync[_, _] =>
val cb = c1.asInstanceOf[DisparcherAsync[Req, Resp]]
cb(req, r => println(r))
handle(new ControllerA())
handle(new ControllerB())
handle {
(req: Request) => Response("callback")
}
handle {
(req: Request, f: (Response) => Unit) =>
f(Response("callback async"))
}
The code work as fine, but the compiler emit a warning with this message on this case case c: DisparcherAsync[_, _]
:
the type test for Playground.DisparcherAsync[, ²] @$4 @$3 cannot be checked at runtime because its type arguments can’t be determined from Playground.ControllerBase
where: _ is a type in method handle with bounds <: Playground.RouteRequest
-
_² is a type in method handle with bounds <: Playground.RouteResponse*
Note that I need to cast the types. Is there any way to get around this situation? I saw something about the TestType class, but I didn’t understand how to fit it into my code.