Looking at:
member this.PostAndReply : (AsyncReplyChannel<'Reply> -> 'Msg) * ?int -> 'Reply
I can’t figure out why the signature looks so counter-intuitive to me. What we want to do is posting a message to an agent, and wait for a reply.
Why do we have to give him a weird function as a ‘message’?
See again this MSDN snippet:
let rec loop() =
printf "> "
let input = Console.ReadLine()
printThreadId("Console loop")
let reply = agent.PostAndReply(fun replyChannel -> input, replyChannel)
if (reply <> "Stopping.") then
printfn "Reply: %s" reply
loop()
else
()
loop()
I’d rather prefer something like this:
member this.PostAndReply : 'Msg * ?int -> 'Reply
Thanks
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
PostAndReplyyou need to give it a function that:'Msg(to be sent to the agent)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
PostAndReplyhad a type'Msg -> 'Reply, the message that the agent receives after it callsReceivewould be of the following type:… 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:
… 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).