【问题标题】:`fail "zero"` as a way to generate Nothing in simple `a -> Maybe a` example`fail "zero"` 作为在简单的 `a -> Maybe a` 示例中生成 Nothing 的一种方式
【发布时间】:2019-05-17 18:26:48
【问题描述】:

我正在阅读a revealing example of using a bind operator

Just 5 >>= (\ x -> if (x == 0) then fail "zero" else Just (x + 1) )

返回Just 6

我对@9​​87654325@ 的行为及其在示例中的用处感到困惑。 看代码的时候我觉得fail "zero"可能有一个意思:

  • 程序永远不会到那个地步
  • 懒惰
  • 别的东西。

然后我意识到,在类型凝聚之后,异常变为Nothing(记录在here)。仍然让我感到困惑的是,没有类型强制 fail 只是程序中的一个错误。

Prelude> fail "zero" :: Maybe Int
Nothing
Prelude> fail "abc" :: [Int]
[]
Prelude> fail "zero"
*** Exception: user error (zero)

我的问题是关于这个例子中fail "zero" 的用处。

(\ x -> if (x == 0) then fail "zero" else Just (x + 1) ) 尝试成为a -> Maybe a 函数的简单案例是否正确?

如果我们只需要 a -> Maybe a 的插图,是什么阻止我们使用 (\ x -> if (x == 0) then Nothing else Just (x + 1) )

我发现下面的这个版本更容易和更短地掌握相同的例子。

Prelude> g x = if (x == 0) then Nothing else Just (x + 1)
Prelude> Just 0 >>= g
Nothing
Prelude> Just 1 >>= g
Just 2

【问题讨论】:

    标签: haskell monads


    【解决方案1】:

    (\ x -> if (x == 0) then fail "zero" else Just (x + 1) ) 尝试成为a -> Maybe a 函数的简单案例是否正确?

    是的。

    如果我们只需要 a -> Maybe a 的插图,是什么阻止我们使用 (\ x -> if (x == 0) then Nothing else Just (x + 1) )

    什么都没有。

    【讨论】:

      【解决方案2】:

      为了详细说明 Daniel 的完全正确答案,fail 是来自 MonadFail 类型类的函数。它最初在 Monad 类型类中,但它并不真正属于那里,因为一些 Monads 没有失败的概念。对于那些确实有失败概念的人,fail 的类型为MonadFail m => String -> m a。也就是说,对于任何实现了MonadFail 接口的类型,以及任何a 类型,fail 都可以接受一个字符串并生成由a 参数化的该类型的实例。

      对于Maybe afail s = Nothing

      对于[a]fail s = []

      对于IO afail 引发包含字符串的异常。

      许多人为Either String a 之类的类型编写MonadFail 的实例,其中fail s = Left s。这不是标准库的一部分的主要原因是因为Either 是一个相当抽象的类型,虽然将Right 视为成功而将Left 视为失败是很常见的,但它可以合理地用作Monad语义翻转。 (例如,如果你想尝试 N 件事情,如果一件事情失败了就继续下一件事情,但取第一个结果,那么你需要使用 Left 作为成功案例。)

      编辑:

      另外,当你写一些类似的代码时

      do 
        Just y <- getMaybe x
        return y
      

      这被取消了:

      do
        case getMaybe x of
          Just y -> return y
          _      -> fail "Failed pattern match"
      

      这意味着失败的模式匹配将在IO a 中引发异常,但在[a] 中为空列表,在Maybe a 中为Nothing

      【讨论】:

      • 感谢您的补充! docsfail 在 do 表达式中的模式匹配失败时被调用。这对其他任何东西有用吗?另一种跟踪失败计算的方法,例如Either?
      • 已编辑帖子以包含“在模式匹配失败时调用”的详细信息。这主要是一种使“失败的计算”在不同类型的Monads 上通用的方法。我最喜欢的用途之一是,您可以编写大量通用代码,而不是 MonadFail,然后只需通过更改类型和一些基本定义来选择您想要的错误类型。
      • 感谢@Izaak Weiss 和MonadFail 工作流程评论!
      猜你喜欢
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-31
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多