Return path dependent type from pattern matching

Given the heterogeneous type:

trait Request {
  type Result
}

trait IntRequest extends Request {
  type Result = Int
}

How can I make the Scala compiler happy to return a path dependent type based on pattern matching:

def test(in: Request): in.Result = in match {
  case i: IntRequest => 1234
  case _ => sys.error(s"Unsupported request $in")
}

Error:

<console>:53: error: type mismatch;
 found   : Int(1234)
 required: in.Result
         case i: IntRequest => 1234
                               ^
+4
source share
2 answers

The following works:

trait Request {
  type Result
}

final class IntRequest extends Request {
  type Result = Int
}

trait Service {
  def handle[Res](in: Request { type Result = Res }): Res
}

trait IntService extends Service {
  def handle[Res](in: Request { type Result = Res }): Res = in match {
    case i: IntRequest => 1234
    case _ => sys.error(s"Unsupported request $in")
  }
}

trait Test {
  def service: Service

  def test(in: Request): in.Result = service.handle[in.Result](in)
}

The compiler only eats it if you use final class, though ?!

+5
source

I think itโ€™s better to use a type class instead of a dependent type pattern matching that needs to be redefined, so in this case we donโ€™t need to redefine the request inside the argument.

trait Request[T] {
  type Result = T
}

trait IntRequest extends Request[Int] {
}

def test[T](in: Request[T]): T = in match {
  case i: IntRequest => 123
  case _ => sys.error(s"Unsupported request $in")
}

test(new IntRequest {}) // 123

test(new Request[String] {}) // error
0
source

Source: https://habr.com/ru/post/1548664/


All Articles