This type signature looks pretty confusing when you see it for the first time, but it does make sense.
The F# library design
The idea behind the is that when you call PostAndReply
you need to give it a function that:
- constructs a message of type
'Msg
(to be sent to the agent)
- after the F# runtime builds a channel for sending messages back to the caller (channels are represented as values of type
AsyncReplyChannel<'Reply>
).
The message that you construct needs to contain the reply channel, but the F# library does not know how you want to represent your messages (and so it does not know how you want to store the reply channel in the message). As a result, the library asks you to write a function that will construct the message for the agent after the system constructs the channel.
Your alternative suggestion
The problem with your suggestion is that if PostAndReply
had a type 'Msg -> 'Reply
, the message that the agent receives after it calls Receive
would be of the following type:
'Msg * AsyncReplyChannel<'Reply>
... so every message received to the agent would also have to carry a channel for sending replies back. However, you probably don't want to send a reply back for every received message, so this wouldn't really work. Maybe you could use something like:
'Msg * option<AsyncReplyChannel<'Reply>>
... but that's just getting more complicated (and it still isn't quite right, because you can only reply to some messages from 'Msg
, but not to all of them).
AsyncReplyChannel<'Reply> -> 'Msg
) additionnally to the body of the agent. Indeed, from a user-centric point of view, I fail to see why would people want to introduce different ways to construct a msg from a reply channel, when callingPostAndReply
, though it would be less generic. – Gery