【问题标题】:Is Monad just a functional way of Error handling?Monad 只是错误处理的一种功能方式吗?
【发布时间】:2018-03-31 06:52:15
【问题描述】:

我正在阅读 “Haskell 编程” 一书,并试图将 Haskell 的想法与我在 C# 中的知识联系起来。如果我错了,请纠正我。

我觉得 monads 强制程序员编写可以处理异常的代码。所以我们会明确提到类型系统中的错误处理,比如

Optional(Int) functionName(Int a, Int b)

返回类型是 Optional(Int) 但不是 Int,所以曾经使用过具有这种返回类型的库的人会理解正在发生错误处理,结果将类似于 None(说明出了什么问题)还有一些(解释我们得到了一些结果)。

任何代码都可能导致快乐路径(我们得到一些结果)和悲伤路径(发生错误的地方)。在类型系统中显式地制作这条路径就是 monad。这就是我对它的理解。请纠正我。

Monad 就像是纯函数式编程和不纯代码之间的桥梁(会产生副作用)。


除此之外,我想确保我对异常处理 (VS) 选项类型的理解。

异常处理尝试在不深入了解输入的情况下执行操作。异常处理很重,因为调用堆栈必须展开直到它到达 Catch ||救援 ||处理代码。

处理事情的函数式方法是在执行操作之前检查输入,如果输入不符合要求的标准,则返回 "None" 作为结果。选项类型是处理错误的轻量级。

【问题讨论】:

  • Optional 只是Monad 的一个实例。还有很多其他的。
  • 请注意,在 C 中没有 option 或 monads 或异常,但仍有错误处理

标签: haskell monads option-type


【解决方案1】:

Monad 只是一个类型可以实现的接口(在 Haskell 术语中,typeclass),以及指定接口行为方式的一些限制的协定。

这与 C# 类型 T 可以实现例如 IComparable<T> 接口的方式没有什么不同。然而,Monad 接口非常抽象,并且函数可以针对不同类型做令人惊讶的不同事情(但始终遵循相同的规律,以及相同的组合“风味”)。

与其将Monad 视为错误处理的一种功能性方式,不如采取另一种方式:发明像Optional 这样表示错误/缺少值的类型,并开始在该类型上设计有用的函数。例如,一个从现有值生成“已居住”Optional 的函数,一个组合两个 Optional-returning 函数以最小化重复代码的函数,一个更改 Optional 中的值(如果存在)的函数,等等。所有这些功能都可以单独使用。

我们有了类型和一系列有用的函数之后,我们可能会问自己:

  • 类型本身是否符合Monad 的要求?例如,它必须有一个类型参数。

  • 我们为该类型发现的一些(不一定是全部)有用函数是否适合Monad 接口?他们不仅必须符合签名,而且必须符合合同。

在肯定的情况下,好消息!我们可以为该类型定义一个Monad 实例,现在我们可以免费使用大量的monad-generic functions

但是即使Monad 类型类在我们的语言中不存在,我们也可以记住,类型和在其上定义的一些函数的行为类似于Monad。来自CompletableFutureJava类的thenCompose方法的documentation

此方法类似于 Optional.flatMap 和 Stream.flatMap。

这允许我们在看似不相关的类之间“传递直觉”,即使我们无法编写单子通用代码,因为共享接口不存在。

【讨论】:

    【解决方案2】:

    Monad 不只是“一种功能性的错误处理方式”,所以你确实错了。

    把这个答案变成monad教程是没有意义的,所以我不打算尝试。理解什么是 monad 需要一些时间,我能给出的最好建议是继续使用这个概念,直到它成功为止。最终会的。

    OP 中描述的类型看起来与 Haskell 更标准的 Maybe 类型等价(同构),这确实是一个 monad。在紧要关头,它可用于错误处理,但更多时候您会使用另一个名为 Either 的 monad(或与其同构的类型),因为它更适合该任务。

    不过,一个 monad 可以是许多其他东西。列表是 monad,函数本身也是(通过 Reader monad)。树也是单子。这些与错误处理无关。

    当谈到 Haskell 中的异常时,我认为它是一个遗留功能。我永远不会围绕异常设计我的 Haskell 代码,因为异常通过类型系统是不可见的。当一个函数可能无法返回结果时,我会让它返回一个Maybe、一个Either,或者其他同构的类型。实际上,这将迫使调用者不仅要处理快乐的路径,还要处理可能发生的任何故障。

    【讨论】:

    • 先生,我想了解列表是如何成为单子的。这意味着 List 可以是空的(不是 int 类型)或者它可能至少有一个整数。您能否分享任何可以将 haskell 想法与一些面向对象编程进行比较的有用资源。
    • 在大多数情况下,返回 Either 值的函数看起来非常像会引发类型检查异常的函数。
    【解决方案3】:

    Monad 只是一种功能性的错误处理方式吗?

    不,不是。 monad 最突出的用途是在 Haskell 中处理副作用计算。它们也可以用于错误处理,但是它们被称为“monads”而不是“错误处理程序”的原因是它们围绕几个看似不同的事物提供了一个通用的抽象。例如,在 Haskell 中,joinconcat 的同义词,=<<concatMap 的中缀同义词。

    Monad 就像是纯函数式编程和不纯代码之间的桥梁(会产生副作用)。

    这是一个微妙的点。在 Haskell 等惰性语言中,副作用指的是可能确实是纯的计算,例如需要在完成时释放内存的 FFI 调用。 Monad 提供了一种跟踪(和执行)副作用的方法。 “纯”只是意味着“函数在使用相同的值调用时返回相同的值”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 2012-02-19
      • 1970-01-01
      • 2017-04-11
      • 2012-08-29
      • 2020-02-16
      相关资源
      最近更新 更多