【问题标题】:Monads and AOP correlation?Monads和AOP相关?
【发布时间】:2018-06-26 12:34:04
【问题描述】:
我正在努力尝试理解函数式编程中的 monad 以及它如何应用于我工作的语言(Swift,一种多范式语言)。
据我所知,Monad 是一种主要处理两个编程问题的模式:链接操作,同时将状态复杂性与其隔离(IO、日志、错误、不确定性)。对吗?
考虑到这一点,似乎 Monads 可用于处理功能解决方案中的事务/原子操作。在我看来(在这一点上)与面向方面编程有一些相似之处:将横切关注点的管理及其复杂性与常规业务逻辑分开。
有意义吗?
谢谢!
PS:这个问题不像“什么是 Monad?”那么广泛。
【问题讨论】:
标签:
swift
haskell
functional-programming
【解决方案1】:
Monad 是计算中几个以前被视为独立的事物的统一。当我说“统一”时,我的意思与物理学家的意思相同:就像牛顿引力将行星轨道与地球弹道学统一起来,麦克斯韦方程统一了电场和磁场一样,单子统一了以下内容:
可能还有一些我已经忘记的。一旦你理解了单子的一般理论,你就会意识到它适用于很多事情,就像 Maxewll 方程打开了整个电磁频谱,而不是我们认为光和无线电是两个独立的现象,因此没有意识到有一些非常有趣的东西在他们之间。
这种普遍性的一个副作用是您可以编写自己的控制流结构。 Haskell 版本的“while”和“for”不是内置的,它们是标准库的一部分。如果你想要一些不同的东西,那么你可以写出来。
monad 中的核心概念是“绑定”(即 (>>=) 运算符)和“返回”(这是一个非常愚蠢的名称,但我们坚持使用它)。这些人必须遵守一些基本的法律。粗略的说,这两个操作是不允许做任何暗中的事情的。所以“return”不允许有任何副作用,并且在“bind”操作的菊花链中重新排列括号也不允许改变程序的含义。
这确实是抽象的东西,这就是为什么在传统命令式语言上长大的程序员看起来很奇怪。只有当你理解了六种不同的单子时,你才会理解这个概念的基本统一。学习 Haskell 的人首先会遇到 IO monad,因为“Hello World”需要它。在那一点上,它看起来就像是一种奇怪的方式来做所有其他编程所做的事情。这是因为 IO monad 是所有其他编程语言(Prolog 除外)工作方式的模型;一系列对现实世界产生影响的动作,包括物理内存中的命名位置。
Haskell monad 的最大优势在于,与其他所有编程语言不同,它不会被困在 IO monad 中。您可以在其他语言中定义 monad,但它们仍会以 Haskell 视为 IO monad 的方式执行。因为 Haskell 是纯粹的,它可以让您摆脱 IO 的约束并将新的 monad 定义为真正的抽象。
【解决方案2】:
很难对单子进行简洁的描述。我对这个问题的看法与@PaulJohnson 略有不同。
在某种意义上,是的,你对 monad 的看法是对的。它们确实允许链接操作和管理复杂性。但也存在其他机制来做到这一点。单子走得更远。
Monad 提供了一个可以在其中执行计算的“上下文”。它们提供了一个结构并遵循一些特定的规则。这些规则很常见,但单个 monad 遵循它们的方式是特定于该 monad 的。
例如:
Option monad 定义了要操作的数据可能存在或不存在的上下文。它根据单子规则如何应用于此特定上下文来遵守单子规则。
List monad 定义了一个上下文,其中它们可以是零个或多个要操作的数据元素。 List monad 的另一种观点是它提供零个或多个 possible 值来操作。这就是为什么在大多数函数式语言中创建多个列表的“叉积”通常很容易。
Future monad(在不同语言中称为不同的事物)定义了一个上下文,在该上下文中要操作的数据可能尚不可用。
还有许多其他 monad,每个 monad 都定义了自己的操作上下文。
monad 遵循的规则允许我们将它们用作抽象,从而有效地隐藏上下文的复杂性,同时在这些上下文中将简单的操作链接在一起。
这真是一个很大的话题。有人建议,没有单一(简单)的答案可以让某人有一个“啊哈”的时刻,他们需要真正理解单子。你必须自己经历斗争才能最终“得到”它。别担心。在您努力更好地理解它们的同时,您可以使用“食谱”食谱来使用 monad。在某些时候它会点击,你会看到大惊小怪的一切。
你会发现自己无法向其他人解释它们。 :)
顺便说一句,在处理 monad 时,我已经多次使用过一些非常好的资源。第一个是 Brian Beckman 的精彩视频,名为 Don't Fear the Monad。第二个是系列博文:Monads are Elephants。
【解决方案3】:
有过于简单化的风险;在world of Monads 中,您应该通过类型系统声明您的方面。因此,编译器会显式跟踪方面,因为您可以编写一个 Monad 来为您处理事务或日志记录问题。
使用monads,您可以静态地(在编译时)声明与核心逻辑分开的效果,而使用 aop,您可以动态地(在运行时)执行此操作,而代数推理的能力要弱得多。进入你的代码库。