在最近简要回顾了Haskell之后,对于monad本质上是什么,有什么简单、简洁、实用的解释?
我发现,我遇到的大多数解释都很难理解,而且缺乏实际细节。
在最近简要回顾了Haskell之后,对于monad本质上是什么,有什么简单、简洁、实用的解释?
我发现,我遇到的大多数解释都很难理解,而且缺乏实际细节。
当前回答
解释monad似乎就像解释控制流语句一样。想象一下,一个非程序员要求你解释它们?
你可以给他们一个涉及理论的解释——布尔逻辑、寄存器值、指针、堆栈和框架。但那太疯狂了。
你可以用语法来解释它们。基本上,C中的所有控制流语句都有大括号,您可以通过它们相对于括号的位置来区分条件和条件代码。这可能更疯狂。
或者,您也可以解释循环、if语句、例程、子例程以及可能的协例程。
Monad可以取代相当多的编程技术。语言中有一种特定的语法支持它们,还有一些关于它们的理论。
它们也是函数式程序员使用命令式代码而不承认它的一种方式,但这并不是他们唯一的用途。
其他回答
如果我理解正确的话,IEnumerable是从monad派生出来的。我想知道,对于我们这些来自C#世界的人来说,这可能是一个有趣的视角吗?
值得一提的是,这里有一些帮助我的教程链接(不,我还不知道单子是什么)。
http://osteele.com/archives/2007/12/overloading-semicolonhttp://spbhug.folding-maps.org/wiki/MonadsEnhttp://www.loria.fr/~kow/monads/
解释“什么是monad”有点像说“什么是数字?”我们总是使用数字。但想象一下,你遇到了一个对数字一无所知的人。你怎么解释数字是什么?你怎么开始描述为什么这可能有用?
什么是单子?简单的回答是:这是一种将操作链接在一起的特定方式。
本质上,您正在编写执行步骤,并将它们与“绑定函数”链接在一起。(在Haskell中,它名为>>=。)您可以自己编写对绑定运算符的调用,也可以使用语法糖,使编译器为您插入这些函数调用。但无论哪种方式,每个步骤都由对该绑定函数的调用分隔。
因此绑定函数就像分号;它将流程中的步骤分开。bind函数的任务是获取上一步的输出,并将其输入下一步。
听起来不太难,对吧?但单子不止一种。为什么?怎样
好吧,bind函数可以从一个步骤中获取结果,并将其传递给下一个步骤。但如果这就是单子的全部。。。这实际上不是很有用。理解这一点很重要:每个有用的monad除了做monad之外,还做其他事情。每一个有用的单子都有一种“特殊的力量”,这使它独一无二。
(没有什么特别作用的monad被称为“身份monad”。与身份函数类似,这听起来是一件毫无意义的事情,但事实证明并非如此……但这是另一回事™.)
基本上,每个monad都有自己的绑定函数实现。你可以编写一个绑定函数,这样它就可以在执行步骤之间做一些傻事。例如:
如果每个步骤都返回一个成功/失败指示符,则只有在前一个步骤成功的情况下,才能让绑定执行下一个步骤。这样,失败的步骤“自动”中止整个序列,而无需您进行任何条件测试。(故障单)扩展这个想法,您可以实现“异常”。(错误单点或异常单点。)因为您自己定义它们,而不是将其作为一种语言特性,所以您可以定义它们的工作方式。(例如,您可能希望忽略前两个异常,仅在引发第三个异常时中止。)您可以使每个步骤返回多个结果,并让bind函数对其进行循环,将每个结果输入到下一步。这样,在处理多个结果时,就不必一直到处写循环。绑定函数“自动”为您完成所有这些。(单子)除了将“结果”从一个步骤传递到另一个步骤之外,还可以让bind函数传递额外的数据。这些数据现在不会显示在源代码中,但您仍然可以从任何地方访问它,而无需手动将其传递给每个函数。(《读者》杂志)您可以这样做,以便可以替换“额外数据”。这允许您模拟破坏性更新,而无需实际执行破坏性更新。(莫纳德州及其堂弟作家莫纳德。)因为您只是在模拟破坏性更新,所以您可以轻松地完成真正的破坏性更新所无法完成的事情。例如,您可以撤消上一次更新,或恢复到旧版本。你可以制作一个可以暂停计算的monad,这样你就可以暂停你的程序,进入并修补内部状态数据,然后恢复它。您可以将“continuations”实现为monad。这可以让你打破人们的想法!
所有这些和更多的都可以通过monad实现。当然,这一切在没有单子的情况下也是完全可能的。使用monad非常简单。
解释monad似乎就像解释控制流语句一样。想象一下,一个非程序员要求你解释它们?
你可以给他们一个涉及理论的解释——布尔逻辑、寄存器值、指针、堆栈和框架。但那太疯狂了。
你可以用语法来解释它们。基本上,C中的所有控制流语句都有大括号,您可以通过它们相对于括号的位置来区分条件和条件代码。这可能更疯狂。
或者,您也可以解释循环、if语句、例程、子例程以及可能的协例程。
Monad可以取代相当多的编程技术。语言中有一种特定的语法支持它们,还有一些关于它们的理论。
它们也是函数式程序员使用命令式代码而不承认它的一种方式,但这并不是他们唯一的用途。
在了解这些信息时,对我帮助最大的两件事是:
第8章,“函数解析器”,摘自Graham Hutton的《Haskell编程》一书。实际上,这根本没有提到monad,但如果您能够通读第章并真正理解其中的所有内容,特别是如何评估一系列绑定操作,您将了解monad的内部结构。预计这需要多次尝试。
关于修道院的教程。这提供了几个很好的例子来说明它们的用途,我不得不说,我在Appendex中的类比是为我工作的。
monad是用于封装状态变化的对象的东西。在不允许您具有可修改状态的语言(例如,Haskell)中最常遇到这种情况。
例如文件I/O。
您将能够使用文件I/O的monad来将不断变化的状态本质与使用monad的代码隔离开来。Monad内部的代码可以有效地忽略Monad外部世界的变化状态,这使您更容易理解程序的整体效果。