I was wondering if there’s no way to achieve the following match in a typesafe way without requiring casts
sealed trait Request { type Response }
case object Foo extends Request { type Reponse = String }
case object Bar extends Request { type Reponse = Int }
case class Baz(num: Int) extends Request { type Reponse = Option[Int] }
val func: (req: Request) => req.Response = {
case Foo => "valid"
case Bar => 3
case Baz(num) => Some(num)
}
Now the compiler complains at each branch with errors like
Found: ("valid" : String)
Required: x$1.Response
I know there are cases like match types with simple patterns where this work, and also some simple adt cases where it works, but it seems path dependent types is not one of them.
IMO this is something that could be fixed in the compiler.
The code in object A already works, so I don’t see why the code in object B shouldn’t work:
object A {
sealed trait Request[Response]
case object Foo extends Request[String]
case object Bar extends Request[Int]
case class Baz(num: Int) extends Request[Option[Int]]
def func[R](req: Request[R]): R = req match {
case _: Foo.type => "valid"
case _: Bar.type => 3
case b: Baz => Option(b.num)
}
}
object B {
sealed trait Request { type Response }
object Request { type Aux[R] = Request { type Response = R } }
case object Foo extends Request { override type Response = String }
case object Bar extends Request { override type Response = Int }
case class Baz(num: Int) extends Request { override type Response = Option[Int] }
def func0[R](req: Request.Aux[R]): R = req match {
case _: Foo.type => "valid" //error
case _: Bar.type => 3 //error
case b: Baz => Option(b.num) //error
}
def func1(req: Request): req.Response = req match {
case _: Foo.type => "valid" //error
case _: Bar.type => 3 //error
case b: Baz => Option(b.num) //error
}
}