我认为使用MailboxProcessor
和CCR的F#代理实现了不同的编程模型,但我相信两者同样强大,虽然肯定有问题可以用其中一个或另一个更好地解决,所以它会很好为邮箱建立另一个F#库。基于CCR的编程模型可能在基于加入微积分如COmega(这是一个旧的MSR项目)的各种语言中更清楚地描述。
例如,你可以比较使用COmega和F#代理的一处缓冲区的实现:
public class OnePlaceBuffer {
private async empty();
private async contains(string s);
public OnePlaceBuffer() { empty(); }
public void Put(string s) & empty() {
contains(s);
}
public string Get() & contains(string s) {
empty();
return s;
}
}
在这个例子中,异步方法的行为就像邮箱(所以有他们四个人:empty
, contains
,Put
和Get
)和尸体的行为那样会触发处理程序时,邮箱的组合包含一个值(即当你把到空缓冲区或当您从0123得到 full buffer)。在F#中,你可以使用MailboxProcessor
写:
type Message<'T> =
| Put of 'T * AsyncReplyChannel<unit>
| Get of AsyncReplyChannel<'T>
MailboxProcessor.Start(fun agent ->
let rec empty = agent.Scan(function
| Put(v, repl) -> repl.Reply(); Some(full(v))
| _ -> None)
and full v = agent.Scan(function
| Get repl -> repl.Reply(v); Some(empty)
| _ -> None)
empty)
的两种实现方式表达了同样的想法,但在一个稍微不同的方式。在F#中,empty
和full
是表示代理的不同状态的两个函数,发送给代理的消息表示代理状态的不同方面(待完成的工作)。在COmega实现中,程序的所有状态都由邮箱捕获。
我猜想,分离需要处理的即时消息代理的状态可能更容易考虑F#MailboxProcessor
了一点,但是这只是一个立即的思想,没有理由......
最后,在F#中使用MailboxProcessor
的现实应用程序中,您很可能会使用更多的这些应用程序,并且它们将以某种方式连接。例如,实现流水线是使用多个MailboxProcessor
实例的应用程序的一个很好的例子(当然,它们都有一些简单的运行异步工作流程)。一个例子见this article。
绝对不是试图解决问题在这里......这纯粹是一个设计考虑。 –
我想我没跟着。我以为你建议一个邮件被限制在一个单一的消息类型中是有问题的,但是一个DU规避了这个“限制”。 – Daniel
同意,但这并没有太多说明这种方法的设计质量。但我不清楚,我会更新我的问题。 –