Search code examples
scalapattern-matchingpath-dependent-type

Returning a path-dependent type from a pattern match


Given a heterogeneous type:

trait Request {
  type Result
}

trait IntRequest extends Request {
  type Result = Int
}

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

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

The error:

<console>:53: error: type mismatch;
 found   : Int(1234)
 required: in.Result
         case i: IntRequest => 1234
                               ^

Solution

  • 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 one uses a final class, though?!