在最近简要回顾了Haskell之后,对于monad本质上是什么,有什么简单、简洁、实用的解释?
我发现,我遇到的大多数解释都很难理解,而且缺乏实际细节。
在最近简要回顾了Haskell之后,对于monad本质上是什么,有什么简单、简洁、实用的解释?
我发现,我遇到的大多数解释都很难理解,而且缺乏实际细节。
当前回答
在了解这些信息时,对我帮助最大的两件事是:
第8章,“函数解析器”,摘自Graham Hutton的《Haskell编程》一书。实际上,这根本没有提到monad,但如果您能够通读第章并真正理解其中的所有内容,特别是如何评估一系列绑定操作,您将了解monad的内部结构。预计这需要多次尝试。
关于修道院的教程。这提供了几个很好的例子来说明它们的用途,我不得不说,我在Appendex中的类比是为我工作的。
其他回答
最近我一直在以不同的方式思考莫纳斯。我一直认为它们以数学的方式抽象出执行顺序,这使得新类型的多态性成为可能。
如果您使用的是命令式语言,并且您按照顺序编写一些表达式,那么代码始终按照该顺序运行。
在简单的例子中,当你使用monad时,感觉是一样的——你定义了一个按顺序发生的表达式列表。除此之外,根据您使用的monad,您的代码可能会按顺序运行(如IO monad),同时在多个项目上并行运行(如List monad);它可能会中途停止(如Maybe monad)。它可能会在中途暂停以稍后恢复(如Resume monad)),或者它可能会中途倒带以尝试其他选项(如逻辑单声道)。
因为monad是多态的,所以可以根据需要在不同的monad中运行相同的代码。
此外,在某些情况下,可以将monad组合在一起(使用monad转换器)以同时获得多个特性。
monad实际上是“类型运算符”的一种形式。它将做三件事。首先,它会将一种类型的值“包装”(或以其他方式转换)为另一种类型(通常称为“一元类型”)。第二,它将使底层类型上的所有操作(或函数)在monadic类型上可用。最后,它将为将自身与另一个monad组合以生成复合monad提供支持。
“可能monad”本质上等同于Visual Basic/C#中的“可为null的类型”。它接受不可为null的类型“T”并将其转换为“可为null<T>”,然后定义所有二进制运算符在可为null><T>上的含义。
副作用也有类似的表现。创建了一个结构,该结构包含函数返回值旁边的副作用描述。当值在函数之间传递时,“提升”操作会复制副作用。
它们被称为“monad”,而不是更容易理解的“类型运算符”的名称,原因如下:
Monad对他们的行为有限制(详见定义)。这些限制,加上涉及三个运算,符合范畴理论中一个叫做monad的结构,这是一个模糊的数学分支。它们是由“纯”函数语言的支持者设计的纯函数语言的支持者,如模糊的数学分支由于数学晦涩难懂,而且monad与特定的编程风格相关,人们倾向于使用monad这个词作为一种秘密握手。正因为如此,没有人费心去投资一个更好的名字。
一个非常简单的答案是:
Monad是一种抽象,它为封装值、计算新的封装值和展开封装值提供了接口。
它们在实践中的方便之处在于,它们提供了一个统一的接口,用于创建建模状态而非状态的数据类型。
必须理解Monad是一种抽象,即用于处理某种数据结构的抽象接口。然后,该接口用于构建具有一元行为的数据类型。
你可以在Ruby中的Monads中找到一个非常好且实用的介绍,第1部分:简介。
如果我理解正确的话,IEnumerable是从monad派生出来的。我想知道,对于我们这些来自C#世界的人来说,这可能是一个有趣的视角吗?
值得一提的是,这里有一些帮助我的教程链接(不,我还不知道单子是什么)。
http://osteele.com/archives/2007/12/overloading-semicolonhttp://spbhug.folding-maps.org/wiki/MonadsEnhttp://www.loria.fr/~kow/monads/
但是,你本可以发明蒙纳斯!
sigfpe说:但所有这些都将单子介绍为需要解释的深奥的东西。但我想说的是,它们一点都不深奥。事实上,面对函数式编程中的各种问题,你会不可避免地被引向某些解决方案,所有这些都是单子的例子。事实上,如果你还没有发明,我希望你现在就发明它们。这是注意到所有这些解决方案实际上都是变相的相同解决方案的一小步。读完这篇文章后,你可能会更好地理解单子上的其他文档,因为你会发现你所看到的一切都是你已经发明的。monads试图解决的许多问题都与副作用有关。因此,我们将从它们开始。(请注意,monad让您做的不仅仅是处理副作用,特别是许多类型的容器对象都可以被视为monad。monad的一些介绍发现,很难协调monad的这两种不同用法,并且只关注其中一种。)在命令式编程语言(如C++)中,函数的行为与数学函数完全不同。例如,假设我们有一个C++函数,它接受一个浮点参数并返回一个浮点结果。从表面上看,它可能有点像一个将实数映射到实数的数学函数,但C++函数可以做的不仅仅是返回一个依赖于其参数的数字。它可以读取和写入全局变量的值,也可以将输出写入屏幕并接收用户的输入。然而,在纯函数语言中,函数只能读取在其参数中提供给它的内容,而它对世界产生影响的唯一方式是通过它返回的值。