I’m working in F# with Akkling so I can use the strongly typed actors on Akka.net but I’ve hit a design limitation within F# and I wondered if there is an elegant way around this.
Take my root message type, I don’t really want to have IActorRef<_> in there because this type will live in a common lib and should not be aware of message system it uses. Also, for easy testing I don’t want to have to create the whole actor system (or test kit).
type MessageType =
| World of WorldMessage
| Location of IActorRef<LocationMessage> * LocationMessage
| Client of IActorRef<LocationMessage> * ClientMessage
A horrible work around is this:
type MessageType<'LocationActor, 'PlayerActor, 'ClientActor> =
| World of WorldMessage<'ClientActor>
| Location of 'LocationActor * LocationMessage<'ClientActor>
| Client of 'ClientActor * ClientMessage<'LocationActor>
Ideally, I would like this but there is a language limitation (Error: Type parameter cannot be used as type constructor):
type MessageType<'a> =
| World of WorldMessage<'a>
| Location of 'a<LocationMessage> * LocationMessage
| Client of 'a<LocationMessage> * ClientMessage
The actual type system problem was already mentioned in the comments (lack of HKTs), but I don't think they're really necessary to solve the design problem here.
You don't want a direct dependency on Akka.NET, but you still want your types to carry a notion of having an actor reference to go with the message. One way around is to introduce your own interface around Actors (either as an actual interface type or a set of functions, depending what makes sense in your context).
So in your common library you have your own IMyActorRef
with whatever you consider a reasonable common subset of IActorRef
functionality:
type IMyActorRef<'msg> =
abstract member Tell: ... -> ...
abstract member Ask: ... -> ...
and define your message type (as well as the actual logic that consumes it) in terms of that interface:
type MessageType =
| World of WorldMessage
| Location of IMyActorRef<LocationMessage> * LocationMessage
| Client of IMyActorRef<ClientMessage> * ClientMessage
And then provide the implementation for it at the point where you reference Akka.NET.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With