Вопрос

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 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).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top