首先声明一下,我对 Monad 的理解还很幼稚。我在这里阅读了有关 Monad 的各种帖子,并对这个概念进行了几个小时的研究。我对这个术语感觉不太舒服,但我认为可以肯定地说我一般理解 Monad 是什么/做什么。
我是一名 C# 开发人员,希望改进我的工作方式。在我的 Monaducation 中进一步帮助我的是看到 C# 中 Monad 的真实应用(即通过 linq SelectMany() 或类似的方法),这显然是对 oldskool C# 中解决同类问题的其他方法的改进。
有人见过这样的野兽吗?
这里有一个这样的场景:您想要编写一个解析库(嵌入式 DSL 的一个很好的例子),并且您发现最好的库是单子解析器组合器库。因此,您可以利用 LINQ 语法糖编写 C# 代码,该代码与您正在解析的语言的语法具有相同的结构,并且您可以从用于即时语义分析和错误恢复的出色编程模型中受益。请参阅此博客了解说明。
求毕达哥拉斯三元组:
var r = from a in Enumerable.Range(1, 25)
from b in Enumerable.Range(a, 25-a)
from c in Enumerable.Range(b, 25-b)
where a*a + b*b == c*c
select new [] { a, b, c };
这是一种这样的场景:您想要编写在不保留线程的情况下进行连续异步调用(例如 IO)的代码,但您不想编写异步编程模型(BeginFoo/EndFoo)强迫您编写的无望的意大利面混乱进入。因此,您可以使用 monad 和 LINQ 糖并编写看起来直线的代码,但它会在整个过程中释放/切换线程。请参阅此博客了解简短说明。
StackOverflow 上的许多解决方案(并且经常在问题中要求)使用 LINQ。使用 LINQ 标签查看问题,您将看到现实世界的用法。
使用 monad 进行编程是声明性的,在高层次上描述你想要什么,而不是如何生成它的低层次细节。
请参阅 Brian Beckman 在第 9 频道的状态单子演讲结尾处的练习。
我最近在博客中讲述了如何将典型的命令式现实世界 C# 代码(NuGet中的函数)重构为函数式、monadic 风格(更具体地说,使用 Maybe monad)。我尽力分步完成,解释步骤背后的原理,所以我认为这有助于理解 monad 的用途。