28 monads haskell functional-programming
可能重复:
什么是monad?
您如何用非编程术语描述monad?是否有一些概念/事物在编程之外(在所有编程之外,而不仅仅是FP),可以说是以一种重要的方式行事或像monad一样?
Shr*_*saR 39
是的,编程之外的一些东西可以说就像monad.不,他们都不会帮助你理解单子.请阅读抽象,直觉和"monad教程谬误":
Joe Haskeller正试图了解monad.在努力了解它们一周后,查看示例,编写代码,阅读其他人写的东西,他终于有了一个"啊哈!"时刻:一切都突然变得清晰,而且Joe理解Monads!当然,真正发生的事情是,乔的大脑将所有细节融合到一个更高层次的抽象中,这是乔可以用来直观地掌握单子的隐喻; 让我们假设Joe的比喻是Monads就像Burritos.乔在这里严重误解了他自己的思维过程:"当然!"乔想."现在这一切都很简单.理解monad的关键是它们像Burritos一样.如果我之前只想到过这个问题!"问题当然是,如果Joe HAD之前想过这个,那就不会有帮助:
但现在乔去写了一个名为"Monads are Burritos"的monad教程,这是一个善意但错误的假设,即如果其他人阅读他的神奇洞察力,那么学习monad对他们来说将是一件轻松的事."莫纳德很容易,"乔写道."将它们视为墨西哥卷饼."乔隐藏了所有关于类型的细节,因为这些都是可怕的,如果人们能够避免所有那些困难和混乱的东西,人们会学得更好.当然,恰恰相反,Joe所做的就是让人们更难了解monad,因为现在他们不得不花一个星期的时间来认为monad是卷饼并且完全混淆,然后一周试图忘记关于墨西哥卷饼的类比,在他们真正开始学习关于monads的事情之前.
正如我在很久以前的另一个回答中所说,sigfpe的文章你可以发明Monads!(也许你已经拥有.),以及Philip Wadler的原始论文Monads的功能性编程,都是出色的介绍(不提供类比,但有很多例子),但除此之外,你只是继续编码,最终它们似乎都会出现不重要的.
[不是一个真正的答案:一个地方monad存在于所有编程之外,当然,是数学.正如这篇热闹的帖子指出的那样,"monad是一个类似于endofunctors的幺半群,问题是什么?" :-)]
编辑:提问者似乎把这个答案解释为居高临下,说像"Monads是如此复杂,他们是无法比拟的".事实上,没有任何类似的东西,而且它的monad-analogies 经常显得居高临下.也许我应该重申我的观点" 你不必了解monad ".你使用特定的monad是因为它们很有用 - 当你需要Maybe类型时使用Maybe monad,你需要IO时使用IO monad,类似的其他例子,显然是在C#中你使用Nullable <>模式,LINQ和查询理解等等.现在,我们称之为monad的所有这些结构的单一通用抽象的洞察力并不是理解或使用特定monad所必需的.在你看到不止一个例子并认识到一种模式之后,这可以作为事后的想法:学习从具体到抽象.直接解释抽象,通过吸引抽象本身的类比,通常不会帮助学习者掌握它是什么的抽象.
Owe*_* S. 25
这是我目前的抨击:
Monads是斗旅:
>>=
操作).return
操作是简单地把东西在桶的操作.>>
)操作的情况下,桶的内容在传递给下一个人之前被转储.下一个人并不关心桶里的东西,他们只是在等待接收它.()
,票据正在桶内传递.它被称为"单位",它只是一张白纸.希望这可以帮助.:-)
编辑:我感谢你的支持,但遗憾的是,Monad教程诅咒再次袭来.我所描述的只是功能应用程序与容器,而不是monad!但我不是虚无主义者 - 我相信Monad Tutorial诅咒可以被打破!所以这是一个更多,更复杂的图片,我认为它描述得更好一些.你决定是否值得你的朋友.
Monads是一个带项目经理的斗式旅.除了该旅的第一个成员外,项目经理都支持其他所有人.斗式旅的成员坐在凳子上,前面有水桶.
第一个人收到一些东西,用它做一些事情,然后把它放在一个桶里.那个人然后放手 - 而不是那个旅的下一个人,这太容易了!:-) - 但是站在那个人后面的项目经理.
项目经理(她的名字是bind,或>>=
)拿走了桶并决定如何处理它.她可能会决定把第一个人的东西从桶里取出来,然后把它交给她面前的人而不用再烦恼了(那就是IO monad).她可能会选择扔掉水桶并结束旅(那是fail
).她可以决定只是绕过她面前的人,水桶传递给下一个经理事不宜迟旅(这是与发生Nothing
在Maybe
单子).她甚至可能决定将这些东西从桶中取出并一次性交给她面前的那个人!(这就是List monad.)在sequence(>>
)的情况下,她只是轻拍她面前的人的肩膀,而不是递给他们任何东西.
当下一个人制作一堆东西时,该人将其交给下一个项目经理.下一个项目经理再次弄清楚如何处理她给的水桶,并把桶里的东西递给她的人.最后,桶被传递回项目经理链,他们可以选择用桶做任务(就像List
组合所有结果的monad).第一个项目经理产生了一桶东西.
在do
语法的情况下,每个人实际上是在之前所有事物的上下文中当场定义的操作 - 好像项目经理不仅传递了桶中的内容,还传递了值(呃,东西)这是由该旅的前任成员产生的.如果使用bind和sequence而不是使用do
语法来编写计算,则更容易看到这种情况下的上下文构建- 注意每个连续的"语句"是在该点之前的操作中构造的匿名函数.
()值,IO monad和return
操作仍然如上所述.
"但这太复杂了!为什么人们不能自己卸下水桶呢?" 我听你问.那么,项目经理可以在幕后做一堆工作,否则会使人的工作复杂化.我们试图让这些旅成员轻松一点,所以他们不必做太多.例如,在Maybe monad的情况下,每个人都不必检查他们给出的内容的价值,看他们是否得到了什么 - 项目经理为他们负责.
"好吧,那么,如果你真的想让每个人的工作变得更轻松,为什么不一直走下去 - 让一个人拿东西拿走东西,让项目经理担心这个问题?" 这通常已经完成,并且它有一个特殊的名称,称为将人(呃,操作)提升到monad中.但是,有时候,你想要一个有更复杂的事情的人,他们想要对所产生的桶进行一些控制(例如,他们是否需要Nothing
在Maybe
monad 的情况下返回),这就是monad的全部内容一般性提供.
要点是:
这样就结束了我的睡前教程.:-P
Mau*_*Mau 14
在非编程术语中:
如果F和G 是一对伴随函子,F左边与G相伴,那么组合GF 就是一个monad.
RD1*_*RD1 12
是否有一些概念/事物在编程之外(在所有编程之外,而不仅仅是FP),可以说是以一种重要的方式行事或像monad一样?
是的,实际上有.通过Curry-Howard同构的扩展,Monads与模态逻辑中的"可能性"直接相关.(参见:模态逻辑的判断重建.)
这是一个非常强大的关系,对我而言,与逻辑方面的可能性相关的概念比与类别理论中的monad相关的概念更直观.我发现向学生解释monad的最好方法是利用这种关系,但没有明确地表明同构.
基本思想是,如果没有monad,所有表达式都存在于同一个世界中,并且所有计算都在该世界中完成.但是对于monad来说,可能存在许多世界,并且计算在它们之间移动.(例如,每个世界可能指定某些可变状态的当前值)
在这种观点中,monad p
意味着"在当前世界可能存在的世界中".
特别是如果t
是一种类型,那么:
x :: t
意味着在当前世界中可以直接获得t类型的东西意味着在当前
y :: p t
可以从当前世界到达的世界中可以获得类型t的东西
然后,return
允许我们将当前世界用作可达世界.
return :: t -> p t
并>>=
允许我们在可达世界中利用某种东西,然后从这个世界到达其他世界.
(>>=) :: p t -> (t -> p s) -> p s
因此>>=
可以用于构建从较小路径到其他世界的可到达世界的路径.
随着世界变得像国家一样,这很容易解释.对于像IO monad这样的东西,它也很简单:一个程序与外部世界的所有交互都指定了一个世界.
对于非终止,两个世界就足够了 - 普通的,以及将来无限远的世界.(应用>> =允许第二个世界,但你不太可能观察到那个世界会发生什么.)对于一个延续monad,当正常使用延续时,世界仍然是相同的,并且当它们有更多的世界时不是(例如,对于callcc).
来自Mike Vanier的精彩帖子,
One of the key concepts in Haskell that sets it apart from other programming languages is the concept of a "monad". People seem to find this difficult to learn (I did as well), and as a result there are loads of monad tutorials on the web, some of which are very good (I particularly like All About Monads by Jeff Newbern). It's even been said that writing a monad tutorial is a rite of passage for new Haskell programmers. However, one big problem with many monad tutorials is that they try to explain what monads are in reference to existing concepts that the reader already understands (I've even seen this in presentations by Simon Peyton-Jones, the main author of the GHC compiler and general Haskell grand poobah). This is a mistake, and I'm going to tell you why.
当试图解释什么是什么时,通过参考其他人已经知道的事情来解释它是很自然的.当新事物在某些方面与其他人熟悉的事物相似时,这种方法很有效.当新事物完全脱离了学习者的经验时,它完全崩溃了.例如,如果你试图向一个从未见过火的穴居人解释火是什么,你会说什么?"它有点像空气和水之间的交叉,但很热......"效果不是很好.类似地,解释原子在量子力学方面的含义是有问题的,因为我们知道电子并不是真的像一颗行星绕着恒星围绕原子核运行,"离域电子云"的概念并不是真的意义重大.费曼曾经说过,没有人真正理解量子力学,而且直觉上也是如此.但在数学水平上,量子力学是众所周知的; 我们对数学的真正含义并没有很好的直觉.
How does this relate to monads? Time and again, in tutorials, blog posts and on the Haskell mailing lists, I've seen monads explained in one of two supposedly-intuitive ways: a monad is "kind of like an action" or "kind of like a container". How can something be both an action and a container? Aren't these separate concepts? Is a monad some kind of weird "active container"? No, but the point is that claiming that a monad is a kind of action or a kind of container is incorrect. So what is a monad, anyway?
Here's the answer: A monad is a purely abstract concept, with no fundamental relationship to anything you've probably ever heard of before. The notion of a monad comes from category theory, which is the most abstract branch of mathematics I know of. In fact, the whole point of category theory is to abstract out all of the structure of mathematics to expose the similarities and analogies between seemingly disparate areas (for instance, between algebra and topology), so as to condense mathematics into its fundamental concepts, and thus reduce redundancy. (I could go on about this for quite a while, but I'd rather get back to the point I'm trying to make.) Since I'm guessing that most programmers learning Haskell don't know much about category theory, monads are not going to mean anything to them. That doesn't mean that they need to learn all about category theory to use monads in Haskell (fortunately), but it does mean that they need to get comfortable thinking about things in a more abstract way than they are probably used to.
请转到帖子顶部的链接阅读完整文章.
在实践中,我使用过的大多数monad都表现得像某种隐含的上下文.
这就像你和朋友试图谈论一个共同的朋友.每当你说"Bob"时,你都指的是同一个Bob,而且由于Bob是你的共同朋友的背景,这个事实只是隐含地穿过你的对话.
当然,您可以与您的老板(而不是您的朋友)讨论您的跳级管理员(而不是您的朋友)恰好被命名为Bob.在这里,您可以进行另一次对话,再次使用一些隐含的含义,这些含义只在对话的上下文中有意义.你甚至可以和你的朋友说出完全相同的词,但由于背景不同,它们会带有不同的含义.
在编程中它是一样的.tell
表现的方式取决于你所处的monad; 信息汇编的方式(>>=
)取决于你所在的monad.同样的想法,不同的谈话方式.
哎呀,即使谈话的规则也可以是monadic."不要告诉任何人我告诉你的事情"隐藏信息的方式与runST
防止引用逃避ST
monad的方式相同.显然,对话可以有层和层的上下文,就像我们有一堆monad变换器一样.
希望有所帮助.