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