【问题标题】:Monads and Actors单子和演员
【发布时间】:2011-04-05 14:47:20
【问题描述】:

我一直在尝试找到任何讨论何时应该优先使用 monad 而不是 actor(在并发场景中),但我什么也没找到。特别是,我想知道反应式扩展(LINQ to Events)与 F# 的 MailboxProcessor 的使用。除了您可能拥有的任何哲学推理之外,请提供示例。

更新 为了更好的上下文,响应式扩展以 IObservable/IObserver 的形式实现了 continuation monad。我不一定说我必须使用 F#,只是说 F# 有一个具体的“演员模型”,可以在 .NET 语言中以 MailboxProcessor 的形式使用。

我想了解的是何时使用 monad(在本例中为 continuation monad)与用于并发目的的 Actor 模型。在 monad(据我所知)不引入状态的地方,actor 有自己的内部状态,可以根据需要进行修改以提供受保护的访问。

我见过很多同时使用的例子:Rx 和 node.js(CPS,不是真正的 continuation monad)与 F# 的 MailboxProcessor 和 Scala 的 Akka 框架。我只是不知道你为什么会选择一个而不是另一个。

【问题讨论】:

  • 这可能对你完全没用,因为我不知道 f# 也不太明白你的问题来自哪里,但我在 haskell 中编写了一个使用 monad 的actor模型实现堆栈(actor 计算是 Reader/IO monad):hackage.haskell.org/packages/archive/simple-actors/0.1.0/doc/…
  • Phil Trelford 还创建了Rx using actors 的实现,因此根据您的操作,您可以使用 monad 或使用 actor 的 monad 来实现 actor。
  • 另一篇“可能对你没有任何用处”的文章。我曾经有人指出,Rx 的主要目的不是引入并发,而是解决它。虽然人们可能认为 F# 代理是一种引入并发性的适当方式。

标签: concurrency f# actor monads system.reactive


【解决方案1】:

你会接受来自 Scala 世界的答案吗?

如果您寻求“演员模型的纯功能替代品”,请参阅 Paul Chiusano 博客中的这篇精彩文章

pchiusano.blogspot.ro/2010/01/actors-are-not-good-concurrency-model.html (存档在这里:http://archive.is/NxNLc

以及下面的一些参考资料:

http://noelwelsh.com/programming/2013/03/04/why-i-dont-like-akka-actors/

演员不作曲 Akka 的 Actors 没有有用的类型 类型系统是我们使用 Scala 的原因。

https://opencredo.com/akka-typed/

不幸的是,当前的 API 存在一些缺陷,这在很大程度上与缺乏类型安全有关

http://doc.akka.io/docs/akka/snapshot/scala/typed.html

此项目的状态以及与 Akka Actors 的关系 Akka Typed 是多年研究和先前尝试的结果(包括 2.2.x 系列中的 Typed Channels),它正在走向稳定,但要对 Akka 的核心概念进行如此深刻的改变还需要很长时间

这样做的一个副作用是,现在可以单独测试行为,而不必将其打包到 Actor 中,测试可以完全同步运行,而不必担心超时和虚假故障。另一个副作用是可以很好地组合和装饰行为

Composable application architecture with reasonably priced monads

Heather Miller 的“函数传递风格”概念可能是分布式函数式编程模型的关键。

SF Scala: Heather Miller, Function-Passing Style, A New Model for Distributed Programming

12/2018 更新:现在我们可以使用Aecor,它提供了以下方法:

  • 使用功能性programming model
  • 实现业务领域逻辑
  • 使用基于runtimeAkka

“行为属于领域层,运行时在基础设施层。”

来源:https://pavkin.ru/aecor-part-3/http://aecor.io

【讨论】:

    【解决方案2】:

    我将回答我自己的问题,并说您应该同时使用两者。这是基于Don Syme's post。 MbP 使用 Async 计算来完成它的工作,而 Async 是一个线程感知的延续 monad。看起来你可以将它单独用于某些用途,但 MbP 肯定需要它。

    我不太喜欢这个答案,我很高兴有人能更好地解释何时使用每个答案。

    更新:

    请参阅 MiniRx,它现在是 FSharpx 的一部分,以了解使用 MailboxProcessor 实现的 Rx 样式 monad 的实现。由于MailboxProcessor 本身是使用async monad 实现的,因此它们确实可以一起工作。它们只是不同的抽象方式。

    【讨论】:

      【解决方案3】:

      我不确定这个问题是否有意义 - 有许多不同的单子(例如身份单子,列表单子,选项单子,...),其中大多数与并发无关。此外,更多地了解您正在处理的特定场景会很有帮助——“并发”是一个有点模糊的话题。根据您要实现的目标,F# 的 async 工作流(基于 Async monad 构建)可能是您的最佳选择。

      如果您使用 F#,我建议您不要直接使用 LINQ-to-anything,因为通过 F# 访问这些库时会有一种非常陌生的感觉。但是,您可以创建令人愉快的 F# 包装器(例如现有的 SeqObservable 模块)。此外,对于 monadic 类型,您可以创建一个计算表达式构建器(例如,您可以使用 Reactive Extensions 创建一个构建器,这将使您能够使用计算表达式来构建和编写IObservables)。

      【讨论】:

      • 我熟悉这些选项。我很好奇为什么以及何时应该选择其中一个。这可能是一种偏好,但我想我会尝试更好地理解。对于一些 F# 到 Rx 包装器,请查看我的 bitbucket 存储库:bitbucket.org/riles01/fsharp.reactive
      • 您似乎正在比较一个具有可独立于计算 (MbP) 填充的后备存储与不具有 (Seq/Observable) 的后备存储。这些是非常不同的情况,并且是特定于应用程序的。
      【解决方案4】:

      请原谅我的新手,因为我刚刚学习 F#。

      如果您有任何相关材料的链接,我很想看到使用 RX 代替 MailboxProcessor。

      以我有限的理解;我会在我自己的代码中选择 MbP,因为在 F# 中设置事件有点混乱(我可以从这篇文章中得到:MSDN)。并且您需要 RX 的事件来挂钩吗?

      与 MbP 一样,我只需要一个可区分的消息联合,即我希望在收到给定消息时执行的功能列表。以及处理此问题的邮箱处理器。

      这一切在代码中看起来都非常简洁。我可以将我的 MbP 捆绑在一个模块中,然后我的“对象”模块看起来像

      • 记录
      • 消息杜
      • 包含一些将数据发布到 MbP 的 getter 和 setter 的包装器

      对我来说,这看起来比如果我用我链接到的 MSDN 文章中描述的事件编写代码时要整洁得多。

      虽然我只是一名 F# 大三学生,所以我的估计可能还有很长的路要走,这是一个外观和感觉的事情,而不是一个适合目的的选择(因为我没有资格做出这样的决定, 然而)

      【讨论】:

      • 根据您公开事件的方式,您只需声明一个事件并将其作为 IObservable 返回,在 Subscribe 方法中调用 Trigger() 方法,所以我不认为事件就是这么糟糕。 MbP 有自己的要求。
      • @jdoig 您所描述的或多或少是 MbP 使用的标准模式。这里有各种各样的例子:fssnip.net/tags/Agent
      • 请注意,您甚至可以从各种内置静态方法生成 observables。我认为您根本不需要设置任何事件,并且代码会更加惯用/功能性 Rx。
      猜你喜欢
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多