Getting variance correct with Akka actors?

83 Views Asked by At

I am frequently encountering the following issue when using generics and Akka actors:

trait AuctionParticipantActor[P <: AuctionParticipant[P]]
  extends StackableActor {


  override def receive: Receive = {
    case message: Handled =>
      participant = participant.handle(message)
      super.receive(message)
    case message =>
      super.receive(message)
  }

  protected var participant: P

}

The AuctionParticipantActor is just a wrapper around an immutable AuctionParticipant. I need that the type P is covariant and I am not sure what is the best way to achieve this.

Alternatively, for my use-cases I don't think I even need to parameterize the AuctionParticipantActor. I could have something like:

trait AuctionParticipantActor
  extends StackableActor {


  override def receive: Receive = {
    case message: Handled =>
      participant = participant.handle(message)
      super.receive(message)
    case message =>
      super.receive(message)
  }

  protected var participant: AuctionParticipant[???]

}

But in this case, I am not sure what to put in place of ??? in order to respect the type bound. If anyone thinks that my problem is with the design, please say so. Thoughts?

1

There are 1 best solutions below

4
On

If you don't use f-bounded-polymorphism why do you need AuctionParticipant to be generic? What is the meaning of type parameter P in AuctionParticipant[P] then? If, as you said, AuctionParticipantActor is just a wrapper over AuctionParticipant and if AuctionParticipantActor is no longer generic then maybe AuctionParticipant shouldn't be either.

trait AuctionParticipantActor
  extends StackableActor {


  override def receive: Receive = {
    case message: Handled =>
      participant = participant.handle(message)
      super.receive(message)
    case message =>
      super.receive(message)
  }

  protected var participant: AuctionParticipant

}

trait AuctionParticipant {
  // ...
}

Otherwise if AuctionParticipant still should be generic (i.e. there is some other meaning of P) then maybe you can use existential type:

trait AuctionParticipantActor
  extends StackableActor {


  override def receive: Receive = {
    case message: Handled =>
      participant = participant.handle(message)
      super.receive(message)
    case message =>
      super.receive(message)
  }

  protected var participant: AuctionParticipant[_]

}

trait AuctionParticipant[P] {
  // ...
}