monad_使用Writer Monad进行事件来源

monad

在先前的文章( F#的Writer Monad 如何登录Apache Spark,一种功能方法 )中,我们讨论了使用Writer monad作为汇总事件的方法的想法。 但是,我们使用的是一个简单的文本记录器,与我们可以在应用程序中使用的任何常规记录器只有很小的区别。

从这种角度来看Writer monad时,似乎为日志记录聚合付出了额外的努力,而实现细节可能会使新手难以理解。

在本文中,我们将介绍Writer monad作为事件聚合器,可以将其以更通用的方式用于不同的用例,这表明它具有更广泛的可用性。 我们还将使用C#来表明该概念不仅与所谓的函数语言紧密相关,而且可以在我们选择的任何环境中使用。

主要思想是提出一种使用事件源概念以及Writer monad作为支持此工作的主要数据结构来聚合事件的方法。

活动采购

事件源是使用不可变结构将传入事件记录到我们的系统中的一种方法,以便我们可以跟踪影响系统状态的事件。 这些事件应在任何时间都可以重播,并且事件的连续流应收敛于可以通过按时间序列方式重播记录的事件而可以恢复或复制的系统状态。

为什么选择作家莫纳德?

Writer monad具有上述相同的特征,它可以记录使当前系统状态发生更改的一般事件。 同时,事件记录在不可变的结构中,而当前状态仅通过应用新事件而改变。

计算器日志

让我们从一个简单的例子开始,一个计算器实现。

我们的计算器可以执行一些操作,但是可以使用Writer monad跟踪其执行的操作。 这个初始示例与我们之前的文章中显示的相似。

请注意,我们的计算器是基于以下将要定义的称为Writer的结构定义的。 主要思想是每个操作仅知道如何使用其执行的操作来创建Writer

Writer monad的定义如下。

在这里,我们定义以下操作。

  • 通过构造函数Bind允许我们创建一个新的Writer
  • Map允许我们更改当前状态。
  • FlatMap会在记录状态更改方式的同时更改当前状态。
  • Unsafe检索当前状态和事件日志。

注意,更改状态的唯一方法是通过.Map.FlatMap

使用此结构,我们可以按以下方式使用计算器。

通过使用.UnSafe()我们可以获得当前状态和事件日志。

在这种情况下,我们仅将Writer monad用作字符串日志,也许正因为如此,到目前为止,这看起来并不那么有趣。 但是,这些是我们接下来的示例的基础。

总和

本示例说明如何使用Writer monad记录系统中发生的一系列整数事件,同时保持流处理器接收的值的总和。

首先定义源代码。

如我们所见,我们将使用无限/无限的随机整数

现在,让我们看看如何使用Writer monad接收和处理这些事件。

当事件是不可变的时,这是事件源的一个非常清楚的示例,通过重播它们,我们可以获得完全相同的最终状态,在这种情况下,该状态是所接收值的总和。

银行账户用例

最后一个示例将展示如何使用Writer monad处理发送到银行帐户的事件。 银行帐户支持两种基本操作,向其中添加资金并从中提取资金。

现在,假设我们有一个事件生成器,该事件生成器生成将由Writer monad作为流处理器处理的事务。

事务由类型ExtractionDeposit ,这两个是我们将要处理的事件类型。

现在我们有了交易源,我们将从初始化初始状态开始。

然后,我们要处理许多事件,在这种情况下,我们对其中的100个事件感兴趣,但是实际上,它可以是任意数目。

请注意,每笔交易我们在银行帐户通过执行相应的操作.FlatMapaccountState

最后,我们能够检索帐户的当前(最终)状态和已处理的事件。

有趣的是,当我们从相同的初始状态开始,然后在Writer monad日志上将相同的事务应用于初始状态时,我们应该以相同的最终状态结束。 值的状态更改是日志上记录的操作的直接结果。

使用纯功能方法

对于那些希望使用纯功能方法并避免变量accountState发生突变的用户,我们可以向IEnumerable<T>添加.FoldLeft方法。 让我们看看如何。

首先,我们添加一个扩展方法,以便可以在C#中执行.FoldLeft

然后,我们只需要更改处理事件的方式即可。

请注意,通过这种方式,我们消除了Writer monad上的突变,而是使用.FoldLeft.FlatMap构建新的.FlatMap

结论

Writer monad提供了一种使用不可变日志来跟踪更改的功能方法,该日志可以在任何编程语言(包括C#)中使用

同样,使用.FlatMap允许我们以流畅的方式链接操作,从而提供声明性的流控制,从而促进不变性。

有时,Writer monad会被误解,并且仅与应用程序日志有关,后者是由副作用库控制的空间。 但是,Writer monad不仅仅是记录器,它还是一个事件源,可用于以一种简洁优雅的方式记录状态变化。

我们还展示了C#如何支持这种方法,证明了Monads不仅仅限于函数式语言。

翻译自: https://hackernoon.com/event-sourcing-using-writer-monad-b26a390285a

monad

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值