Using ask pattern from outside of typed system: Type mismatch

akka-typed

(Willem Vermeer) #1

Hi there,
In the examples we see that it’s possible to use ActorRef.ask to send a typed message to a typed actor and receive a Future[Response]. It seems to be required to use a local variable to define this future before interacting with it. So this works:

  case class PrintMe(message: String, ref: ActorRef[Response])
  case class Response(response: String)

  val printBehavior: Behavior[PrintMe] = Behaviors.receive {
    case (ctx, PrintMe(msg, ref)) =>
      println(s"Received message $msg")
      ref ! Response(s"Thanks for sending $msg")
      Behaviors.same
  }
  val system = ActorSystem(printBehavior, "simple-ask")

  private val future: Future[Response] = system ? (ref => PrintMe("test1", ref))

  future.onComplete {
    case Success(r) => r match {
      case r1: Response => println(s"Executed fine with response ${r1.response}")
    }
    case Failure(t) => t.printStackTrace()
  }

But invoking onComplete directly like so:

// compiler error!
  (system ? (ref => PrintMe("test1", ref))).onComplete {
    case Success(r) => r match {
      case r1: Response => println(s"Executed fine with response ${r1.response}")
    }
  }

results in a compiler error on the second occurrence of ref:
Type mismatch, expected: ActorRef[Forum.Response], actual: ActorRef[Nothing]

The same error appears when I try:

// compiler error!
  for {
    response <- system ? (ref => PrintMe("test1", ref))
  } yield response

I have tried using upcast or asInstanceOf but to no avail. I must be missing something?

Thanks,
Willem


(Willem Vermeer) #2

Found the answer to my question - I had to give the compiler one more hint about what we’re doing by adding the type to the first declaration of ref:

  (system ? ((ref: ActorRef[Response]) => PrintMe("test1", ref))).onComplete {
    case Success(r) => r match {
      case r1: Response => println(s"Executed fine with response ${r1.response}")
    }
  }

(Johan Andrén) #3

I think this is the same type inference issue tracked here: https://github.com/akka/akka/issues/25611

Will hopefully work without the explicit type with the next Scala version.