如何模式匹配F#akka.net中收到的消息类型?

use*_*547 1 f# pattern-matching akka.net

请参阅上次编辑.

为新手问题道歉.我正在尝试使用Akka.net在F#中实现一些东西.我对F#很新,我只使用了Scala的Akka.基本上我试图在Scala中实现一些非常简单的东西,即让Actor根据它接收的消息类型做不同的事情.

我的代码如下,它是对akka.net网站上提升的hello world示例的略微修改.我相信我的代码的第一个问题是它确实记录模式匹配而不是类型模式匹配,但是我无法编写没有编译错误的类型匹配...任何帮助将不胜感激.谢谢.

open Akka.FSharp
open Actors
open Akka
open Akka.Actor

type Entries = { Entries: List<string>}

let system = ActorSystem.Create "MySystem"

let feedBrowser = spawn system "feedBrowser" <| fun mailbox -> 
    let rec loop() = actor {
        let! msg = mailbox.Receive()
        match msg with 
        | { Entries = entries} -> printf "%A" entries
        | _ -> printf "unmatched message %A" msg 
        return! loop()}
    loop()

[<EntryPoint>]
let main argv = 

    feedBrowser <! "abc"        // this should not blow up but it does

    system.AwaitTermination()

    0
Run Code Online (Sandbox Code Playgroud)

编辑:错误是运行时的一个,System.InvalidCastException,无法将类型为String的对象强制转换为条目.

稍后编辑:我使用此更改,向下转换为Object:

let feedBrowser = spawn system "feedBrowser" <| fun mailbox -> 
    let rec loop() = actor {
        let! msg = mailbox.Receive()
        let msgObj = msg :> Object
        match msgObj with 
        | :? Entries as e  -> printfn "matched message %A" e
        | _ -> printf "unmatched message %A" msg 
        return! loop()}
    loop()
Run Code Online (Sandbox Code Playgroud)

现在这两行正常工作

feedBrowser <! "abc"
feedBrowser <! { Entries = ["a"; "b"] }
Run Code Online (Sandbox Code Playgroud)

第一个打印"不匹配的消息abc",第二个输出条目.

没有演员阵容,有更好的方法吗?akka.net是否有专门针对此案例的内容?谢谢.

Rod*_*dal 6

您应该使用Discriminated Union(在此示例中为Command类型).然后你可以模式匹配它的选项.

type Entries = { Entries: List<string>}

type Command = 
    | ListEntries of Entries
    | OtherCommand of string

let stack() = 

    let system = ActorSystem.Create "MySystem"

    let feedBrowser = spawn system "feedBrowser" <| fun mailbox -> 
        let rec loop() = actor {
            let! msg = mailbox.Receive()
            match msg with 
            | ListEntries { Entries = entries} -> printf "%A" entries
            | OtherCommand s -> printf "%s" s
            return! loop() }
        loop()
Run Code Online (Sandbox Code Playgroud)

要发送您应该使用的消息:

feedBrowser <! OtherCommand "abc"
feedBrowser <! ListEntries { Entries = ["a"; "b"] }
Run Code Online (Sandbox Code Playgroud)

重要的是说send运算符具有以下签名:

#ICanTell -> obj -> unit
Run Code Online (Sandbox Code Playgroud)

因此,如果您传递具有不同类型的消息(如字符串),则会引发异常.