F# 邮箱与 MailboxProcessor
我注意到 Mailbox 类型是封装的,只能通过 MailboxProcessor 来使用。
这意味着要拥有一个可以向其发布消息的代理,我必须拥有单一类型的单个邮箱(或以一种奇特的方式使用现有的 MailboxProcessor)。
我是否应该理解,为单个工作流程设置多个邮箱必然会导致糟糕的设计? Ccr 显然为您提供了这种程度的自由。
编辑: 正如 Daniel 指出的,如果想要发送多种消息类型,DU 可以优雅地解决问题 - 而且我过去也不是没有这样做过。
但问题是,这样做不是有代码味道吗?随着时间的推移,添加更多类型的消息发送给代理是否会导致您承担太多责任?我有时认为始终将代理消耗的消息类型封装在接口后面非常重要,这样该信息就不会暴露。
I notice the Mailbox type is encapsulated and can only be used through the use of the MailboxProcessor.
It implies that to have an agent to which I can post messages, I'm forced to have a single Mailbox of a single type (or use the existing MailboxProcessor in an exotic way).
Should I understand that having multiple Mailbox for a single workflow would inherently result in a bad design? The Ccr clearly gives you that level of freedom.
Edit:
As Daniel pointed out, if one wants to send multiple message types, DUs elegantly solves the problem - and it's not like I haven't done that in the past.
But the question is, isn't doing that a code smell? Wouldn't adding more types of messages sent to an agent over time lead you into have too many responsibilities? I sometimes think it would be important to always encapsulate the message types the agent consumes behind an interface such that this information is never exposed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为使用 MailboxProcessor 和 CCR 的 F# 代理实现了不同的编程模型,但我相信两者同样强大,尽管肯定存在可以使用其中之一更好地解决的问题,所以它如果有另一个围绕邮箱构建的 F# 库就好了。基于 CCR 的编程模型可能在基于连接演算的各种语言中得到更清晰的描述,例如COmega (这是一个旧的 MSR 项目)。
例如,您可以比较使用 COmega 和 F# 代理的单位缓冲区的实现:
在此示例中,异步方法的行为类似于邮箱(因此有四个:
empty
、contains
、Put
和Get
),主体的行为类似于处理程序,当邮箱组合包含值时(即当您put< /em> 进入空缓冲区或当您从满缓冲区获取时)。在 F# 中,您可以使用MailboxProcessor
并编写:这两个实现表达了相同的想法,但方式略有不同。在 F# 中,
empty
和full
是两个函数,代表代理的不同状态,发送到代理的消息代表代理状态的不同方面(待处理的工作) 。在 COmega 实现中,程序的所有状态都由邮箱捕获。我猜想,将代理的状态与需要处理的即时消息分开可能会让您更容易地思考一下 F# MailboxProcessor,但这只是一个没有理由的直接想法...
最后,在 F# 中使用
MailboxProcessor
的实际应用程序中,您很可能会使用大量它们,并且它们将以某种方式连接。例如,实现管道是使用多个 MailboxProcessor 实例的应用程序的一个很好的示例(当然,所有实例都具有一些与其关联的简单运行异步工作流)。有关示例,请参阅本文。I think that F# agents using
MailboxProcessor
and CCR implement a different programming model, but I believe that both are equally powerful, although there are definitely problems that could be more nicely solved with one or the other, so it would be nice to have another library for F# built around mailboxes. The programming model based on CCR is probably more clearly described in various languages based on join calculus such as COmega (which is an old MSR project).For example, you can compare an implementation of one-place buffer using COmega and F# agents:
In this example, the async methods behave like mailboxes (so there are four of them:
empty
,contains
,Put
andGet
) and the bodies behave like handlers that will be triggered when a combination of mailboxes contains a value (i.e. when you put into an empty buffer or when you get from a full buffer). In F#, you could useMailboxProcessor
and write:The two implementations express the same ideas, but in a slightly different way. In F#,
empty
andfull
are two functions that represent different state of the agent and messages sent to the agent represent different aspect of the agent's state (the pending work to do). In the COmega implementation, all state of the program is captured by the mailboxes.I guess that separating the state of the agent from the immediate messages that need to be processed might make it easier to think about F#
MailboxProcessor
a bit, but that's just an immediate thought with no justification...Finally, in a realistic application that uses
MailboxProcessor
in F#, you'll quite likely use a larger number of them and they will be connected in some way. For example, implementing pipelining is a good example of an application that uses multipleMailboxProcessor
instances (that all have some simple runnning asynchronous workflow associated with them, of course). See this article for an example.通常,消息类型是可区分联合,它允许在单个邮箱中容纳各种类型的消息。这对你的情况不起作用吗?
Generally the message type is a discriminated union, which allows for various kinds of messages within a single mailbox. Does that not work in your case?
我认为您永远无法仅使用一种类型的消息成功处理邮箱,除非您使用响应式扩展中的
ISubject
类型。信息有不同的形式,但都很重要。我能想到的两个主要示例是:您的想法是正确的,您很可能希望将数据消息限制为某种类型,但从技术上讲,DU 是一种有多种选择的类型。如果您采用与 Luca 相同的方法,即在《L'Agent》中采用他最初的动态方法,我想他和我都会同意,一个邮箱中包含太多类型是一个挑战。
I don't think you would ever be able to successfully work with a mailbox using only one type of message, unless you use something like the
ISubject
type from the Reactive Extensions. Messages come in different forms, and all are important. The two primary examples I can think of are:You are correct in thinking that you would most likely want to restrict the data messages to a certain type, but technically a DU is one type with many alternatives. If you were to go for the same approach as Luca with his initial, dynamic approach in L'Agent, I think both he and I would agree that too many types in one mailbox is a bit of a challenge.
我想我可能已经找到了我正在寻找的东西。我已经听了 Rich Hickey 的演讲(我们到了吗)至少 5 次,我相信他的方法解决了我的许多设计问题。显然,这可以通过 F# 邮箱或 CAS 引用来实现。
我真的推荐它并且很高兴听到一些反馈。
I think I may have found what I was looking for. I have listened to Rich Hickey's talk (Are we there yet) at least 5 times and I believe his approach solves many of the design concerns I had. Obviously this can be implemented with either F# Mailboxes or CAS references.
I really recommend it and would be happy to hear some feedback.