Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何定义F#actor函数以避免消息装箱?_F#_Akka.net - Fatal编程技术网

如何定义F#actor函数以避免消息装箱?

如何定义F#actor函数以避免消息装箱?,f#,akka.net,F#,Akka.net,NET提供了一个F#API,使得在Akka邮箱上将Akka参与者定义为F#函数变得非常简单。只要actor处理的所有消息都可以使用一个有区别的联合来描述,actor邮箱就是强类型的。问题在于,将所有消息定义放在一个类型(有区别的联合)中往往会使该类型变得混乱:参与者通常会响应不同类别的消息,例如远程客户端发送的消息和内部通信中使用的消息。例如,参与者可以生成内部作业并得到内部组件的通知。使用不同的(内部)类型定义这些内部消息是有意义的,但是actor的邮箱更改不再是强类型,actor的函数如下所

NET提供了一个F#API,使得在Akka邮箱上将Akka参与者定义为F#函数变得非常简单。只要actor处理的所有消息都可以使用一个有区别的联合来描述,actor邮箱就是强类型的。问题在于,将所有消息定义放在一个类型(有区别的联合)中往往会使该类型变得混乱:参与者通常会响应不同类别的消息,例如远程客户端发送的消息和内部通信中使用的消息。例如,参与者可以生成内部作业并得到内部组件的通知。使用不同的(内部)类型定义这些内部消息是有意义的,但是actor的邮箱更改不再是强类型,actor的函数如下所示:

    let rec loop () =

        actor {
            let! message = mailbox.Receive ()
            match box message with
            | :? PublicMessage as msg -> handlePublicMessage msg
            | :? PrivateMessage as msg -> handlePrivateMessage msg
            | _ -> raise (InvalidOperationException(sprintf "Invalid message type %A" message))

            return! loop ()
        }

    loop ()
let handleMessage message =
    match message with
    | PublicMessage as msg -> handlePublicMessage msg
    | PrivateMessage as msg -> handlePrivateMessage msg
    | _ -> raise (InvalidOperationException(sprintf "Invalid message type %A" message))

let actorRef = spawn system "my-actor" <| actorOf handleMessage
我不喜欢的是,这种方法剥夺了F#的核心优势之一:类型推断。相反,我们必须将消息装箱,将其转换为对象类型,然后将其转换为我们期望的类型

这种方法有两种选择:

  • 始终在同一类型下列出所有邮件案例。糟糕,糟糕,糟糕
  • 为每个消息类型定义一个参与者类型。我认为这甚至是值得的,因为创建新的参与者类型的决定不应该由特定于语言的约束驱动

  • 我检查了来自Akka.NET训练营的代码,他们正在使用第一种方法——消息装箱和施法。这是最好的办法吗?

    好的,在我看来有两个问题——内部消息和装箱/打字安全

    据我所知,actor模型没有私有消息。演员要么能对信息做出反应,要么不能。如果您真的想要一个异步私有逻辑,我建议在处理公共消息时使用异步函数,而不是另一个参与者消息,因为它必须是公共的

    对于类型安全性,虽然我还没有尝试过,但似乎有另一种方法可以避免使用计算表达式生成actor,并使用提供的generic
    actorOf
    函数,如下所示:

        let rec loop () =
    
            actor {
                let! message = mailbox.Receive ()
                match box message with
                | :? PublicMessage as msg -> handlePublicMessage msg
                | :? PrivateMessage as msg -> handlePrivateMessage msg
                | _ -> raise (InvalidOperationException(sprintf "Invalid message type %A" message))
    
                return! loop ()
            }
    
        loop ()
    
    let handleMessage message =
        match message with
        | PublicMessage as msg -> handlePublicMessage msg
        | PrivateMessage as msg -> handlePrivateMessage msg
        | _ -> raise (InvalidOperationException(sprintf "Invalid message type %A" message))
    
    let actorRef = spawn system "my-actor" <| actorOf handleMessage
    
    let handleMessage消息=
    将消息与匹配
    |PublicMessage as msg->handlePublicMessage msg
    |PrivateMessage as msg->handlePrivateMessage msg
    |->raise(InvalidOperationException(sprintf“无效消息类型%A”消息))
    
    让actorRef=spawn系统“我的演员”我没有使用Akka.NET的经验。如果唯一的问题是混合了公共和私有消息类型,那么是否允许使用嵌套的歧视联合?即:类型消息=PublicMsg的Public | Private of privateMg;PublicMsg和PrivateMg都是受歧视的工会。谢谢。我知道actorOf和actorOf2,但它们并没有真正解决消息降级的问题,以防一个参与者处理多个消息类型。我也在Akka.NET gitter聊天中讨论了这一点,得出的结论是限制在于F#语言能力。