我正在阅读"在Haskell编程" 预定并尝试将haskell的想法与我在C#中的知识联系起来。如果我错了,请纠正我。
我觉得monad强制程序员编写可以处理异常的代码。所以我们将明确提到类型系统中的错误处理,如
Optional(Int) functionName(Int a, Int b)
返回类型是Optional(Int)但不是Int,所以谁曾经使用具有这种返回类型的库将理解错误处理正在发生并且结果将像None(解释出错)和一些(解释我们得到了一些结果)。
任何代码都可能导致Happy Path(我们得到一些结果)和Sad Path(发生错误)。在类型系统中明确地创建这个路径就是monad。这就是我对它的理解。请纠正我。
Monads就像是Pure Functional Programming和Impure代码之间的桥梁(会产生副作用)。
除此之外,我想确保我对异常处理(VS)选项类型的理解。
异常处理尝试在不深入查看输入的情况下执行操作。异常处理很重,因为调用堆栈必须放松才能到达Catch ||救援||处理代码。
处理事物的功能方法是在执行操作之前检查输入并返回"无" 作为结果,如果输入符合所需条件。选项类型是处理错误的轻量级。
答案 0 :(得分:5)
Monad
只是一个类型可以实现的接口(在Haskell术语,类型类中),以及指定接口应该如何表现的一些限制的契约。
与C#类型T
如何实现,例如IComparable<T>
接口没有什么不同。然而,Monad
界面非常抽象,并且函数可以针对不同类型做出惊人不同的事情(但始终遵循相同的规律,以及相同的“组合风味”)。
不要将Monad
视为错误处理的功能方式,而是采用另一种方式:发明类似Optional
的类型,表示错误/缺少值,并开始设计有用的函数那种类型。例如,一个从现有值产生“居住”Optional
的函数,一个组成两个Optional
的函数 - 返回函数以最小化重复代码,这是一个改变{{1}内部值的函数如果它存在,依此类推。所有这些功能都可以自己使用。
在之后我们有了类型和一系列有用的功能,我们可能会问自己:
类型本身是否符合Optional
的要求?它必须有一个类型参数,例如。
我们为类型适合Monad
接口发现了一些(不一定是所有)有用的函数吗?他们不仅必须符合签名,还必须符合合同。
在肯定的情况下,好消息!我们可以为该类型定义Monad
实例,现在我们可以免费使用大量monad-generic functions!
但即使我们的语言中不存在Monad
类型类,我们也可以记住,它上面定义的类型和一些函数的行为类似于Monad
。来自Monad
Java类的thenCompose
方法的documentation:
此方法类似于Optional.flatMap和Stream.flatMap。
这允许我们在看似无关的类之间“转移直觉”,即使我们不能编写monad-generic代码,因为共享接口不存在。
答案 1 :(得分:3)
Monads不仅仅是“错误处理的功能方式”,所以你确实是错的。
将这个答案变成monad教程是毫无意义的,所以我不打算尝试。理解monad是什么需要一些时间,我能给出的最好的建议是继续使用这个概念,直到它点击为止。最终它会。
OP中描述的类型看起来与Haskell更标准的Maybe
类型相同( isomorphic ),它确实是一个monad。在紧要关头,它可以用于错误处理,但更常见的是你使用另一个名为Either
的monad(或类型同构),因为它更适合于该任务。
当谈到Haskell中的异常时,我认为这是一个遗留功能。我永远不会围绕异常设计我的Haskell代码,因为通过类型系统看不到异常。当一个函数可能无法返回结果时,我会让它返回一个Maybe
,一个Either
或另一个同构的类型。实际上,这将迫使调用者不仅要处理幸福的路径,还要处理可能发生的任何故障。
答案 2 :(得分:0)
Monad只是错误处理的一种功能方式吗?
不,不是。 monads最突出的用途是处理Haskell中的副作用计算。它们也可用于错误处理,但它们被称为&#34; monads&#34;而不是&#34;错误处理程序&#34;是因为它们围绕着几个看似不同的东西提供了一个共同的抽象。例如,在Haskell中,join
是concat
的同义词,=<<
是concatMap
的中缀同义词。
Monads就像是Pure Functional Programming和Impure代码之间的桥梁(会产生副作用)。
这是一个微妙的观点。在诸如Haskell之类的惰性语言中,副作用指的是可能确实是纯粹的计算,例如需要在完成时释放内存的FFI调用。 Monads提供了一种跟踪(和执行)副作用的方法。 &#34;纯&#34;简单地表示&#34;函数在使用相同的值&#34;。
调用时返回相同的值