Search code examples
genericsf#grpcinterceptor

Return value from gRPC Interceptor in F# without knowing return type


I am trying to implement a Grpc.Core.Interceptors.Interceptor in F#. Simplified, my interceptor method takes a UnaryServerMethod<'request, 'response> and returns a 'response. I know what I want to return when 'response is a particular type. But I don't know how to return it within the F# type system when the return type is generic.

Here is my current code:

type ExceptionInterceptor() =
  inherit Grpc.Core.Interceptors.Interceptor()
  with
    override _.UnaryServerHandler(request, context, continuation: UnaryServerMethod<'request, 'response>) =
      task {
        try
          return! continuation.Invoke(request, context)
        with e ->
          return
            if typeof<'response> = typeof<MyResponse> then
              // Compiler error:
              // The 'if' expression needs to have type ''a' to satisfy context type requirements. 
              // It currently has type 'MyResponse'.
              generateFromException e // returns type MyResponse
            else
              raise e
      }

Solution

  • I don't think this is going to be possible within the F#/.NET type system. The problem is that your if test happens at run-time, but code generation is done at compile-time. You and I know that the true branch will only be taken when 'response is MyResponse, but the compiler still has to generate code for that branch that works for all types, not just MyResponse. That means that generateFromException has to be generic for the code to compile.