12

見つめている:

member this.PostAndReply : (AsyncReplyChannel<'Reply> -> 'Msg) * ?int -> 'Reply

署名が私にとって直感に反しているように見える理由がわかりません。私たちがやりたいのは、エージェントにメッセージを投稿し、返信を待つことです。なぜ私たちは彼に「メッセージ」として奇妙な機能を与えなければならないのですか?

このMSDNスニペットをもう一度参照してください。

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

私はむしろこのようなものを好みます:

member this.PostAndReply : 'Msg * ?int -> 'Reply

ありがとう

4

1 に答える 1

9

この型注釈は、初めて見るとかなり紛らわしいように見えますが、それは理にかなっています。

F#ライブラリの設計
の背後にある考え方は、呼び出すときに次のような関数PostAndReplyを指定する必要があるということです。

  • タイプのメッセージを作成します'Msg(エージェントに送信されます)
  • F#ランタイムがメッセージを呼び出し元に送り返すためのチャネルを構築した後(チャネルはタイプの値として表されますAsyncReplyChannel<'Reply>)。

作成するメッセージには応答チャネルが含まれている必要がありますが、F#ライブラリはメッセージをどのように表現するかを認識していません(したがって、応答チャネルをメッセージにどのように格納するかを認識していません)。その結果、ライブラリは、システムがチャネルを構築した後にエージェントへのメッセージを構築する関数を作成するように要求します。

別の提案提案
の問題PostAndReplyは、タイプがあった場合'Msg -> 'Reply、エージェントが呼び出した後に受信するメッセージReceiveは次のタイプになることです。

'Msg * AsyncReplyChannel<'Reply>

...したがって、エージェントに受信されたすべてのメッセージは、応答を送り返すためのチャネルも伝送する必要があります。ただし、受信したメッセージごとに返信を送りたくない場合は、これは実際には機能しません。多分あなたは次のようなものを使うことができます:

'Msg * option<AsyncReplyChannel<'Reply>>

...しかし、それはますます複雑になっています(そして、からの一部のメッセージにしか返信でき'Msgず、すべてのメッセージに返信できないため、まだ完全には正しくありません)。

于 2012-02-29T15:10:56.443 に答える