无法使用邮箱处理器(F#)保持状态



我正在尝试创建一个字符串列表,该列表在邮箱处理器的帮助下逐渐将元素逐渐插入异步。但是我没有得到所需的输出。

我几乎遵循了https://fsharpforfunandprofit.com/posts/concurrency-actor-model/的代码但是,在我的情况下,它似乎不如预期。我拥有的代码如下:

type TransactionQueue ={
queue : string list
} with
static member UpdateState (msg : string) (tq : TransactionQueue) =
    {tq with queue = (msg :: tq.queue)}
static member Agent = MailboxProcessor.Start(fun inbox ->
                            let rec msgLoop (t : TransactionQueue) =
                                async{
                                   let! msg = inbox.Receive()
                                   let newT = TransactionQueue.UpdateState msg t
                                   printfn "%A" newT
                                   return! msgLoop newT
                                }
                            msgLoop {queue = []}
                        )
static member Add i = TransactionQueue.Agent.Post i

[<EntryPoint>]
let main argv =
// test in isolation
printfn "welcome to test"
let rec loop () =
    let str = Console.ReadLine()
    TransactionQueue.Add str
    loop ()
loop ()

0 

我不断获得的结果仅是最新输入的列表,状态不保留。因此,如果我输入" a",则" b",那么" c"队列只有值" c",而不是" a";" b";" c"

任何帮助或指针都将不胜感激!

就像c#属性一样,您的Agent确实是一个属性,因此表现得像具有void参数的方法。这就是为什么您每次访问Agent属性时都会获得新代理的原因。

在惯用的F#中,实现代理时有两种样式。如果您不需要很多代理实例,只需编写一个模块并将与代理相关的内容封装在其中。否则,应使用OOP样式。

样式#1的代码

module TransactionQueue =
    type private Queue = Queue of string list
    let private empty = Queue []
    let private update item (Queue items) = Queue (item :: items)
    let private agent = MailboxProcessor.Start <| fun inbox ->
        let rec msgLoop queue = async {
            let! msg = inbox.Receive ()
            return! queue |> update msg |> msgLoop
        }
        msgLoop empty
    let add item = agent.Post item
[<EntryPoint>]
let main argv =
    // test in isolation
    printfn "welcome to test"
    let rec loop () =
        let str = Console.ReadLine()
        TransactionQueue.add str
        loop ()
    loop ()

样式#2的代码

type Queue = Queue of string list with
    static member Empty = Queue []
    static member Update item (Queue items) =
        Queue (item :: items)
type Agent () =
    let agent = MailboxProcessor.Start <| fun inbox ->
        let rec msgLoop queue = async {
            let! msg = inbox.Receive ()
            return! queue |> Queue.Update msg |> msgLoop
        }
        msgLoop Queue.Empty
    member this.Add item = agent.Post item
[<EntryPoint>]
let main argv =
    // test in isolation
    printfn "welcome to test"
    let agent = new Agent ()
    let rec loop () =
        let str = Console.ReadLine()
        agent.Add str
        loop ()
    loop ()

请注意,Queue类型的单盘联合类型的使用。

最新更新