最近有很多关于 monad 的讨论。我已经阅读了几篇文章/博客文章,但我无法深入了解他们的示例以完全掌握这个概念。原因是 monad 是一个函数式语言概念,因此示例使用的是我没有使用过的语言(因为我没有深入使用过函数式语言)。我无法深入掌握语法以完全理解文章......但我可以说那里有一些值得理解的东西。
但是,我非常了解 C#,包括 lambda 表达式和其他函数特性。我知道 C# 只有功能特性的一个子集,因此可能无法在 C# 中表达 monad。
但是,一定可以传达这个概念吗?至少我希望如此。也许您可以提供一个 C# 示例作为基础,然后描述 C# 开发人员希望可以从那里做什么,但由于该语言缺乏函数式编程特性而不能。这太棒了,因为它会传达 monad 的意图和好处。所以这是我的问题:您可以向 C# 3 开发人员提供有关 monad 的最佳解释是什么?
谢谢!
(编辑:顺便说一下,我知道至少有 3 个“什么是 monad”的问题已经在 SO 上了。但是,我面临着同样的问题......所以我需要这个问题,因为C#-开发者焦点。谢谢。)
最佳答案
您整天在编程中所做的大部分工作是将一些函数组合在一起以从中构建更大的函数。通常,您的工具箱中不仅有函数,还有运算符、变量赋值等其他东西,但通常您的程序将大量“计算”组合在一起,形成更大的计算,这些计算将进一步组合在一起。
monad 是执行这种“计算组合”的某种方式。
通常将两个计算组合在一起的最基本的“运算符”是;
:
a; b
当你这样说时,你的意思是“首先执行a
,然后执行b
”。结果 a; b
基本上又是一种可以与更多东西组合在一起的计算。
这是一个简单的单子(monad),它是一种将小计算组合成大计算的方法。 ;
表示“先做左边的事,然后再做右边的事”。
另一个在面向对象语言中可以被视为 monad 的东西是 .
。通常你会发现这样的事情:
a.b().c().d()
.
基本上意味着“评估左侧的计算,然后根据计算结果调用右侧的方法”。这是另一种将函数/计算组合在一起的方法,比 ;
稍微复杂一点。使用 .
将事物链接在一起的概念是一个 monad,因为它是一种将两个计算组合在一起以形成一个新计算的方法。
另一个没有特殊语法的相当常见的 monad 是这种模式:
rv = socket.bind(address, port);
if (rv == -1)
return -1;
rv = socket.connect(...);
if (rv == -1)
return -1;
rv = socket.send(...);
if (rv == -1)
return -1;
-1 的返回值表示失败,但没有真正的方法来抽象出此错误检查,即使您有很多 API 调用需要以这种方式组合。这基本上只是另一个 monad,它根据规则组合函数调用“如果左边的函数返回 -1,我们自己返回 -1,否则调用右边的函数”。如果我们有一个运算符 >>=
来做这件事,我们可以简单地写:
socket.bind(...) >>= socket.connect(...) >>= socket.send(...)
这将使事情更具可读性,并有助于抽象出我们组合函数的特殊方式,这样我们就不需要一遍又一遍地重复自己。
还有更多的方法可以组合函数/计算,这些函数/计算可作为通用模式使用,并且可以在 monad 中抽象,使 monad 的用户能够编写更加简洁明了的代码,因为所有的簿记所用功能的管理在 monad 中完成。
例如,上面的 >>=
可以扩展为“进行错误检查,然后在我们作为输入获得的套接字上调用右侧”,这样我们就不需要多次显式指定 socket
:
new socket() >>= bind(...) >>= connect(...) >>= send(...);
正式定义有点复杂,因为你必须担心如何将一个函数的结果作为下一个函数的输入,如果那个函数需要那个输入,并且你想确保你的函数combine 适合您尝试将它们组合到 monad 中的方式。但基本概念只是将不同的方法形式化以将功能组合在一起。
关于c# - 在 C# 中,什么是 monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/674855/