我正在阅读" haskell中的编程" 书籍,并试图将Haskell的想法与我在C#中的知识相关联。如果我错了,请纠正我。
我觉得Monads强制执行程序员编写可以处理异常的代码。因此,我们将明确提及类型系统中的错误处理,例如
Optional(Int) functionName(Int a, Int b)
返回类型是可选的(int(,而不是int,因此谁曾经使用具有这种返回类型的库会理解发生错误处理正在发生,结果将是没有的(解释出了问题出了问题(还有一些(解释我们得到了一些结果(。
任何代码都可以导致快乐路径(我们得到一些结果(和悲伤的路径(发生错误的地方(。Monad是在类型系统中明确进行此路径。那是我对此的理解。请纠正我。
单子就像纯粹的功能编程和不纯正代码之间的桥梁(这会导致副作用(。
除此之外,我想确保我对异常处理(VS(选项类型的理解。
例外处理试图进行操作,而无需更深入地了解输入。异常处理很重,因为呼叫堆栈必须放松,直到到达捕获量为止||救援||处理代码。
处理事务的功能方法是在执行操作之前检查输入,并返回" none" 作为结果,如果输入不符合所需的标准。选项类型是处理错误的轻质重量。
Monad
只是一个接口(用haskell enter,Typeclass(,类型可以实现,并与合同一起实现指定界面应如何表现的一些限制。
与C#类型T
可以实现IComparable<T>
接口没有什么不同。但是,Monad
界面非常抽象,功能可以为不同类型做出令人惊讶的不同事物(但始终尊重相同的法律,并且构图的"风味"(。
,而不是将Monad
视为一种功能性错误处理方式,而是更好地走:发明一种类型的Optional
类型,该类型代表错误/不存在值,并开始在该类型上设计有用的功能。例如,从现有值中产生"居住的" Optional
的函数,该函数构成了两个 Optional
返回函数以最小化重复代码,该函数会更改Optional
内部的值(如果存在(,等等。所有这些功能都可以自己有用。
我们有类型和一系列有用的功能,我们可能会问自己:
-
类型本身是否符合
Monad
的要求?它必须具有类型参数。 -
do (不一定是所有(我们发现的适合
Monad
接口的类型的有用功能?他们不仅必须适合签名,还必须适合合同。
在肯定的情况下,好消息!我们可以为该类型定义一个Monad
实例,现在我们可以免费使用大量的单一生成功能!
但是,即使我们的语言中不存在Monad
Typeclass,我们也可以记住,所定义的类型和某些功能的行为就像Monad
。从CompletableFuture
Java类的thenCompose
方法的文档中:
此方法类似于可选的flatmap和stream.flatmap。
这使我们能够在看似无关的类之间"转移直觉",即使我们不能编写Monad-Generic代码,因为共享界面不存在。
monads不仅仅是'错误处理方式',所以您确实是错误的。
将这个答案变成单一的教程将是毫无意义的,所以我不会尝试。它需要一些时间才能了解一个单子是什么,而我能提供的最好的建议是继续处理该概念,直到它点击为止。最终会。
OP中描述的类型看起来等效(同构(与Haskell更为标准的Maybe
类型,这确实是单一的。在紧缩中,它可用于错误处理,但更常见您会使用另一个称为Either
的单元(或类型的同构(,因为它更适合该任务。
单子可以是许多其他事情。列表和函数本身(通过读取器 monad(都是单月。树木也是单子。这些与错误处理无关。
当涉及Haskell的例外时,我认为这是一项旧功能。我永远不会在例外设计我的haskell代码,因为通过类型系统看不到例外。当功能可能无法返回结果时,我会让它返回Maybe
,Either
或其他类型的同构。的确,这将迫使呼叫者不仅要处理快乐路径,还要处理任何可能发生的故障。
monad只是一种功能性的错误处理方式吗?
不,不是。单调最突出的用途是处理Haskell中的副作用计算。它们也可以用于错误处理,但是它们被称为" monads"而不是"错误处理程序"的原因是,它们围绕几个看似不同的东西提供了共同的抽象。例如,在Haskell中,join
是concat
的同义词,=<<
是concatMap
的Infix同义词。
单子就像纯粹的功能编程和不纯正代码之间的桥梁(这会导致副作用(。
这是一个微妙的点。用诸如Haskell之类的懒惰语言,副作用是指确实是纯粹的计算,例如需要在完成后释放内存的FFI调用。Monads提供了一种跟踪(和执行(副作用的方法。"纯"简单地表示"函数在以相同值调用时返回相同的值"。